您的位置:首页 > 其它

HDU 1171 Big Event in HDU(01背包)

2014-10-20 22:01 260 查看
HDU 1171 Big Event in HDU(01背包)
http://acm.hdu.edu.cn/showproblem.php?pid=1171
题意:

给你N种物品,每种物品有m[i]个,且具有v[i]的价值,现在你要把所有的物品分成A和B两堆,且A堆的总价值要>=B堆的总价值 且 要使得A堆与B堆的价值尽量接近, 问你A和B堆的总价值分别为多少?

分析:

假设所有物品的总价值为sum,由于B堆价值<=A堆价值,且它们需要尽量接近. 所以我们只需要让B堆的价值<=sum/2的前提下尽量大即可. 也就是说让B选所有物品(B选剩下的自然归A所有),且要求”
B堆的价值<=sum/2的前提下尽量大”. 现在就是一个背包问题了. 但是每个物品可能有m[i]个,我们直接把m[i]个相同的物品看成m[i]个不同的(但具有相同价值v[i]的)物品即可.

下面就是解01背包问题了. 假设dp[i][j]==x表示处理完前i个物品且总价值<=j时,最多可以获得的价值为x,那么:

dp[i][j] = max( dp[i-1][j] , dp[i-1][j-v[i]]+v[i])

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=250000+5;

int n;
int v[5000+5];
int dp[maxn];

int main()
{
    int N;
    while(scanf("%d",&N)==1 && N>0)
    {
        n=0;
        int sum=0;//物品价值总和
        while(N--)
        {
            int vi,m;
            scanf("%d%d",&vi,&m);
            while(m--)
            {
                v[++n]=vi;//添加每件物品
                sum+=vi;
            }
        }
        memset(dp,0,sizeof(dp));

        for(int i=1;i<=n;i++)
        {
            for(int j=sum/2;j>=v[i];j--)
                dp[j]=max(dp[j], dp[j-v[i]]+v[i]);
        }

        printf("%d %d\n",sum-dp[sum/2],dp[sum/2]);
    }
    return 0;
}


AC代码2:
优化下界bound后


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=250000+5;

int n;
int v[5000+5];
int dp[maxn];

int main()
{
    int N;
    while(scanf("%d",&N)==1 && N>0)
    {
        n=0;
        int sum=0;//物品价值总和
        while(N--)
        {
            int vi,m;
            scanf("%d%d",&vi,&m);
            while(m--)
            {
                v[++n]=vi;//添加每件物品
                sum+=vi;
            }
        }
        memset(dp,0,sizeof(dp));

        int s[5000+5];
        s[n+1]=0;
        for(int i=n;i>=1;i--)
            s[i]=s[i+1]+v[i];

        for(int i=1;i<=n;i++)
        {
            int bound=max(sum/2-s[i+1], v[i]);
            for(int j=sum/2;j>=bound;j--)
                dp[j]=max(dp[j], dp[j-v[i]]+v[i]);
        }

        printf("%d %d\n",sum-dp[sum/2],dp[sum/2]);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: