您的位置:首页 > 其它

hdu 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

2013-09-02 00:21 183 查看
        hdu 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

        01背包的对物品的选择方案只有 0(不拿) 和 1(拿)吧, 完全背包对一件物品i的选择就有 k 种啦, k <= v / cost[i] (v为背包总量, cost[i]为i物品的花费) 

        多重背包, 拆分物品分成多件, 这里是用2的幂作为拆分因子的.

        假如当一件物品i的数量c和价值p的乘积c*p大于背包总量时, 可以认为物品i的数量无限啦, 所以就可以转化为完全背包咯. 否则就进行拆分, 把问题转为01背包. 

        拆分的目的就是为了转化问题为 01背包.

#include <stdio.h>
#include <string.h>

#define MAX 300

int dp[MAX], c[MAX], w[MAX], cnt[MAX];
int n, v;

inline int max(int a, int b) {
return a > b ? a : b;
}

inline void zeroOnePack(int cost, int weight) {
for (int j = v; j >= cost; j--) {
dp[j] = max(dp[j], dp[j - cost] + weight);
}
}

inline void completePack(int cost, int weight) {
for (int j = cost; j <= v; j++) {
dp[j] = max(dp[j], dp[j - cost] + weight);
}
}

inline void multiplePack(int cost, int weight, int count) {
if (cost*count >= v) {
completePack(cost, weight);
return ;
}

int k = 1;
while (k <= count) {
zeroOnePack(k*cost, k*weight);
count -= k;
k *= 2;
}

if (cnt > 0) {
zeroOnePack(count*cost, count*weight);
}
}

int main() {
int T;
int i, j;

while (scanf("%d", &T) != EOF) {
while (T--) {
memset(dp, 0, sizeof(dp));
scanf("%d%d", &v, &n);
for (i = 1; i <= n; i++) {
scanf("%d%d%d", &c[i], &w[i], &cnt[i]);
}

for (i = 1; i <= n; i++) {
multiplePack(c[i], w[i], cnt[i]);
}

printf("%d\n", dp[v]);
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  背包问题
相关文章推荐