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;

}

 

 

 

你可能感兴趣的:(HDU)