题目链接:
思路:找每次最多装一半的情况,注意数组范围,前几次dp开小了,一直RE。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int dp[500100],val[50500]; int main(void) { int n,i,j,k,sum,ans1,ans2,res,tp; int v,m,num; while(cin>>n&&n>0) { //if(n==0) continue; sum=0;num=0; for(i=0;i<n;i++) { cin>>v>>m; sum+=v*m; for(j=1;j<=m;j*=2) { val[num++]=j*v; m-=j; } if(m>0) { val[num++]=j*m; } } res=sum/2; memset(dp,0,sizeof(dp)); for(i=0;i<num;i++) { for(j=res;j>=val[i];j--) { dp[j]=max(dp[j],dp[j-val[i]]+val[i]); } } ans1=dp[res]; ans2=sum-ans1; if(ans1<ans2) tp=ans1,ans1=ans2,ans2=tp; cout<<ans1<<" "<<ans2<<endl; } return 0; }