杭电1171(一维背包+完全背包)

http://acm.hdu.edu.cn/showproblem.php?pid=1171

题目意思:

要求:把给出的物品分给两个学院,保证前个必须大于后一个院。给出的数据是:物品的价值,和数目.

思路:一开始我想到直接一维背包,后来想想,不行,万一在球的中途求得只并非最大,但是你有判断不了。因此这里可能不能直接一维背包不能解决,但是必须加是上完全背包,对每一个组数据,进行判断(与总和的一半),这样就分成两中情况。不会道导致超出的。

分析:根据完全背包与一维背包的定义!!可以的的出。

详细见代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std ;
const int maxn=55;
int dp[150005];
int val[maxn];
int num[maxn];
int n;
int main()
{
    int i,j,k,x,y,sum,ans;
    while(scanf("%d",&n)!=EOF)
    {
        if(n<0)break;
        ans=0;
        for(i=1;i<=n;i++)
        {
          scanf("%d%d",&val[i],&num[i]);
          ans+=val[i]*num[i];
        }
        sum=ans/2;
       memset(dp,0,sizeof(dp));
        for(i=1;i<=n;i++)
        {
           if(val[i]*num[i]>=sum)//判断出是否超出一半的价值。
           {
              for(k=val[i];k<=sum;k++)
               {
                   dp[k]=max(dp[k],dp[k-val[i]]+val[i]);//找出最大的值,靠近sum的值。。(并且小于或等于sum)不会超过sum。
               }
           }
           else
           {
              for(x=1;x<=num[i];x++)
              {
                  for(y=sum;y>=val[i];y--)
                  {
                      dp[y]=max(dp[y],dp[y-val[i]]+val[i]);//若是小于sum。则直接遍历一遍,求出最大的值。依次增加。
                  }
              }
           }
        }
        printf("%d %d\n",ans-dp[sum],dp[sum]);

    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/u010200793/article/details/16369611
今日推荐