Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 16224 Accepted Submission(s): 5725
题目意思就是n种东西,知道价值和数量。问尽量分成两份,两份对应的价值,先输出大的,再输出小的。
以前用母函数做的,今天做DP复习了下,貌似直接用多重背包更加简单。想想以前的母函数的题目,貌似很多时候都可以换成背包做的
#include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <string> #include <set> #include <map> #include <vector> using namespace std; const int MAXN=250010; int dp[MAXN]; int nValue; //0-1背包,代价为cost,获得的价值为weight void ZeroOnePack(int cost,int weight) { for(int i=nValue;i>=cost;i--) dp[i]=max(dp[i],dp[i-cost]+weight); } //完全背包,代价为cost,获得的价值为weight void CompletePack(int cost,int weight) { for(int i=cost;i<=nValue;i++) dp[i]=max(dp[i],dp[i-cost]+weight); } //多重背包 void MultiplePack(int cost,int weight,int amount) { if(cost*amount>=nValue)CompletePack(cost,weight); else { int k=1; while(k<amount) { ZeroOnePack(k*cost,k*weight); amount-=k; k<<=1; } ZeroOnePack(amount*cost,amount*weight); } } int a[55],b[55]; int main() { int n; while(scanf("%d",&n)==1) { if(n<0)break; nValue=0; for(int i=0;i<n;i++) { scanf("%d%d",&a[i],&b[i]); nValue+=a[i]*b[i]; } memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) { if(b[i]==1)ZeroOnePack(a[i],a[i]); else MultiplePack(a[i],a[i],b[i]); } int t=nValue/2; while(dp[t]!=t)t--; printf("%d %d\n",nValue-t,t); } return 0; }