hdu 1171 dp(多重背包)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//hdu 1171 dp(多重背包) //题意:把所有物品的价值尽量分为相等的两份,不能等分的话 //后面那份可以稍小于前面的 //求出价值总和后,令价值的一半为背包容量,让背包尽可能的装满 #include <stdio.h> #include <string.h> //最多50种,每种最多100个,每个价值最大50 //所以所有物品总价值为250000,我们只要dp一半就可以了 #define N 130000 #define M 55 int tot_n; int val[M], num[M]; bool dp[N]; int main() { while(scanf("%d", &tot_n), tot_n >= 0) { int sum_v = 0; memset(dp, false, sizeof(dp)); for(int i = 0; i < tot_n; ++i) { scanf("%d%d", &val[i], &num[i]); sum_v += val[i] * num[i]; } int half = sum_v / 2; dp[0] = true; for(int i = 0; i < tot_n; ++i) { //j 要从后往前,若从0开始,i=0 时(即第i中物品时),在s循环中, //val[i]*s = 10, j = 0的话,val[10] 就会为true,当j 等于10时 又把i种物品放一次 //但 dp[10] 本应该是 false 的 //若j 从大到小,比如 j = 10时 dp为true,然后放入 val[i]=10 的物品,则标记val[10+10]=true //意思是 容纳的质量为 10 时放入 质量为 10 的物品,则容纳的质量可达到20,则标记为true //标记的是 j 的后面,而j 时递减的,所以不会影响到 dp[j] == true这个判断 if(half - val[i] >= 0) //没有这个判断就会超时,也不知道为什么 { //for 的判断应该就会判断了,但他就是超时了,无语 for(int j = half - val[i]; j >= 0; --j) //表示背包已经装有 j 的容量 { if(dp[j] == true) { //s记录i中器材的数量 for(int s = 1; s <= num[i] && val[i]*s + j <= half; s++) dp[ val[i]*s + j ] = true; } } } } int i; for(i = half; i >= 0; --i) //找背包尽可能装满的大小 if(dp[i] == true) break; printf("%d %d\n", sum_v - i, i); } return 0; }