|
思路:
由于一共有5种物品,每种物品最多只能有5个,所以物品的拥有情况,可以表示为 6*6*6*6*6 中状态。 这个数好像是 7k 多,不大。 状态转移发生在有折扣的时候,如果当前的状态可以打折,那么就看打折之后是否会比现在划算就可以了。
一开始用的是取模,后来改成位操作了,快了一点,但还是很慢,不明白那些0ms怎么来的,⊙﹏⊙b汗 代码很烂,仅供参考
#include <stdio.h>

int S, B;
int price[1024], code[1024];
int offer[128], cut[128];
int ans[1 << 15];

inline int min(int a, int b)
  {
return a < b ? a : b;
}

int main()
  {
int c, k, i, j, n, t, m[5], a, b;

freopen("e:\\test\\in.txt", "r", stdin);

scanf("%d", &B);
t = 0;
 for (i = 0; i < B; i++) {
scanf("%d%d%d", &c, &k, &price[i]);
t |= k << (i*3);
code[c] = i;
}
scanf("%d", &S);
 for (i = 0; i < S; i++) {
scanf("%d", &n);
offer[i] = 0;
 while (n--) {
scanf("%d%d", &c, &k);
offer[i] |= k << (code[c]*3);
}
scanf("%d", &cut[i]);
}
 for (i = 0; i <= t; i++) {
ans[i] = 0;
a = i;
 for (j = 0; j < B; j++) {
ans[i] += price[j] * (a & 7);
a >>= 3;
}
 for (j = 0; j < S; j++) {
a = i;
b = offer[j];
 for (k = 0; k < B; k++) {
if ((a & 7) < (b & 7))
break;
a >>= 3;
b >>= 3;
}
if (k < B)
continue;
ans[i] = min(ans[i], ans[i - offer[j]] + cut[j]);
}
}
printf("%d\n", ans[t]);

return 0;
}

|