提供多重背包的一些思路
Description
Input
Output
Sample Input
Sample Output
网上的代码:
#include #include #include using namespace std; int dp[100000],sum,ans; struct st { int v; int m; }data[100000]; void full(int x) { for(int i=data[x].v;i<=ans;i++) dp[i]=max(dp[i],dp[i-data[x].v]+data[x].v); } void one(int x) { for(int j=1;j<=data[x].m;j++) for(int i=ans;i>=data[x].v;i--) dp[i]=max(dp[i],dp[i-data[x].v]+data[x].v); } int main() { int i,j,n; while(scanf("%d",&n)&&(n>0)) { memset(dp,0,sizeof(dp)); sum=0; for(i=1;i<=n;i++) { scanf("%d%d",&data[i].v,&data[i].m); sum+=data[i].v*data[i].m; } ans=sum/2; for(i=1;i<=n;i++) { if(data[i].v*data[i].m>=ans) full(i); else one(i); } printf("%d %d\n",sum-dp[ans],dp[ans]); } return 0; }
//母函数方法:
/*注意将数组a,s清零,WA了好几次,测试数据都过。。无语。 */ #include #include int a[250010],s[250010]; int v[55],m[55]; int main() { int n,i,j,k,sum,ans; while(scanf("%d",&n)&&n>0) { sum=0; memset(s,0,sizeof(s)); memset(a,0,sizeof(a)); for(i=1;i<=n;i++) { scanf("%d%d",&v[i],&m[i]); sum+=v[i]*m[i]; } for(i=0;i<=v[1]*m[1];i+=v[1])//注意变化。 { s[i]=1; } for(i=2;i<=n;i++) { for(j=0;j<=sum;j++) { for(k=0;k+j<=sum&&k<=v[i]*m[i];k+=v[i]) { a[k+j]+=s[j]; } } for(k=0;k<=sum;k++) { s[k]=a[k]; a[k]=0; } } for(i=sum/2;i>=0;i--) { if(s[i]) { printf("%d %d\n",sum-i,i); break; } } } return 0; }
我的代码:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<climits>
#include<queue>
#include<vector>
#include<map>
#include<sstream>
#include<set>
#include<stack>
using namespace std;
//typedef long long ll;
//ifstream fin("input.txt");
//ofstream fout("output.txt");
//fin.close();
//fout.close();
int val[60];
int num[60];
int n;
int dp[270000];
int main()
{
int i,j,k;
while(scanf("%d",&n)==1&&n>0)
{
int cnt=0;
for(i=1;i<=n;i++)
{
scanf("%d%d",&val[i],&num[i]);
cnt+=num[i]*val[i];
}
int sum=cnt/2;
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
for(j=1;j<=num[i];j++)
{
for(k=sum;k>=val[i];k--)
{
dp[k]=max(dp[k],dp[k-val[i]]+val[i]);
}
}
}
printf("%d %d\n",cnt-dp[sum],dp[sum]);
}
return 0;
}