1171 Big Event in hdu 解题报告

    题目不难。背包问题,上限是总和的一半。可以转化成01背包问题,也可以用多重背包解决。下面是笔者的AC代码:

#include <iostream>
using namespace std;

char dp[250001];
int v[51];
int m[101];

int main()
{
    int i,j,k,n,max,t,sum;
    while(cin>>n)
    {
        if(n<0)
            continue;
        for(sum=i=0;i<n;i++)
        {
            cin>>v[i]>>m[i];
            sum+=v[i]*m[i];
        }
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        max=sum/2;
        for(i=0;i<n;i++)
            for(j=max;j>=0;j--)
                if(dp[j])
                    for(k=1;k<=m[i];k++)
                        dp[j+v[i]*k]=1;
        for(i=sum/2;i>=0;i--)
            if(dp[i])
                break;
        cout<<sum-i<<' '<<i<<endl;
    }
}

    最后先输出sum-i的原因是sum/2<=sum-sum/2.

    额,虽然过了,但是时间差强人意,93MS。在网上找到的另外一份代码,基本是模板了,我改了一点点,时间是31MS,贴在下面了。

#include<stdio.h>
#include<string.h>
int dp[200001],w[101],num[101],V;

inline int max(int a,int b)
{
    return a>b?a:b;
}

void ZeroOnePack(int cost,int weight)
{
    for(int i=V;i>=cost;i--)
        dp[i]=max(dp[i],dp[i-cost]+weight);
}

void CompletePack(int cost,int weight)
{
    for(int i=cost;i<=V;i++)
        dp[i]=max(dp[i],dp[i-cost]+weight);
}

void MultiplePack(int cost,int weight,int amount)
{
    if(amount*cost>=V)
    {
        CompletePack(cost,weight);
        return ;
    }
    int k=1;
    while(k<amount)
    {
        ZeroOnePack(cost*k,weight*k);
        amount-=k;
        k+=k;
    }
    ZeroOnePack(amount*cost,amount*weight);
}

int main()
{
    int n,i,sum;
    while(scanf("%d",&n),n>0)
    {
        sum=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d %d",&w[i],&num[i]);
            sum+=w[i]*num[i];
        }
        V=sum>>1;
        memset(dp,0,sizeof(*dp)*(V+1));
        for(i=1;i<=n;i++)
            MultiplePack(w[i],w[i],num[i]);
        printf("%d %d\n",sum-dp[V],dp[V]);
    }
    return 0;
}

    我会把代码改改的。。。31MS的那份代码的多重背包的函数中用了2分的思想,这可能就是原因吧。虽然有模板,我还是喜欢自己敲敲。

    将我的代码用上二分。。。时效46MS,估计有误差。0MS的代码又是怎样的呢?

#include <iostream>
using namespace std;

int dp[250001];
int s[51];
int num[51];

int main()
{
    int i,j,k,max,up,up2,n,t,tn;
    while(~scanf("%d",&n))
    {
        if(n<0)
            continue;
        dp[up=max=0]=1;
        for(i=0;i<n;i++)
        {
            scanf("%d%d",s+i,num+i);
            up+=s[i]*num[i];
        }
        up2=up/2;
        for(i=0;i<n;i++)
        {
            for(k=1;k<num[i];k*=2)
            {
                num[i]-=k;
                for(j=max;j>=0;j--)
                {
                    if(dp[j]&&(t=j+s[i]*k)<=up2)
                    {
                        dp[t]=1;
                        if(max<t)
                            max=t;
                    }
                }
            }
            {
                for(j=max;j>=0;j--)
                {
                    if(dp[j]&&(t=j+s[i]*num[i])<=up2)
                    {
                        dp[t]=1;
                        if(max<t)
                            max=t;
                    }
                }
            }
        }
        printf("%d %d\n",up-max,max);
    }
}

 

posted @ 2013-02-10 16:43  SF-_-  阅读(167)  评论(0编辑  收藏  举报