题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1171
思路:dp[i]>0表示可以达到价值为i的状态。初始dp[0]=0,其他为-inf;从总价值的一半出开始查找可以达到的状态即可。
原始写法
#include<cstdio>
using namespace std;
const int num=250005;
int dp[num],cw[53],np[53],n,m;
int max(int a, int b)
{
if(a>b)
return a;
return b;
}
void ZeroOnePack(int c,int w)
{
int i;
for(i=m;i>=c;i--)
dp[i]=max(dp[i],dp[i-c]+w);
}
void CompletePack(int c,int w)
{
int i;
for(i=c;i<m;i++)
dp[i]=max(dp[i],dp[i-c]+w);
}
int main()
{
int i,j,k,temp;
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
if(n<0) break;
m=0;
for(i=0;i<n;i++)
{
scanf("%d%d",&cw[i],&np[i]);
m+=cw[i]*np[i];
}
for(i=0;i<=m;i++)
dp[i]=-1000000000;
dp[0]=0;
for(i=0;i<n;i++)
{
if(np[i]==1)
ZeroOnePack(cw[i],cw[i]);
else if(np[i]*cw[i]>=m)
CompletePack(cw[i],cw[i]);
else
{
k=1;
temp=np[i];
while(k<temp)
{
ZeroOnePack(k*cw[i],k*cw[i]);
temp=temp-k;
k*=2;
}
ZeroOnePack(temp*cw[i],temp*cw[i]);
}
}
for(i=m/2;i>=0;i--)
if(dp[i]>=0)
break;
printf("%d %d\n",m-i,i);
}
return 0;
}
比较偷懒的x