hdu 1171 dp(多重背包)

View Code
//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;
}

 

 

 

posted @ 2012-04-15 15:14  gabo  阅读(179)  评论(0编辑  收藏  举报