[Uva12260]Free Goodies(dp+贪心)
解题关键:先对p进行排序,消除p的影响,然后对w进行01背包即可。注意p对w的约束。j<=(cur+1)/2
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> #include<iostream> using namespace std; typedef long long ll; struct node{ int p,w; bool operator<(const node& a)const{ return p>a.p||(p==a.p&&w<a.w); } }nod[1002]; int dp[1002][1002],cost[1002][1002],t,n; string s; int main(){ cin>>t; while(t--){ int sum=0; memset(dp,0,sizeof dp); memset(cost,0,sizeof cost); cin>>n>>s; for(int i=1;i<=n;i++) cin>>nod[i].p>>nod[i].w,sum+=nod[i].p; sort(nod+1,nod+n+1); int cur=0; for(int i=s[0]=='P'?2:1;i<=n;i++){ cur++; for(int j=1;j<=(cur+1)/2;j++){ dp[i][j]=dp[i-1][j]; cost[i][j]=cost[i-1][j]; if(j!=1&&!dp[i-1][j-1]) continue; if(dp[i][j]<dp[i-1][j-1]+nod[i].w){ dp[i][j]=dp[i-1][j-1]+nod[i].w; cost[i][j]=cost[i-1][j-1]+nod[i].p; }else if(dp[i][j]==dp[i-1][j-1]+nod[i].w){ cost[i][j]=min(cost[i][j],cost[i-1][j-1]+nod[i].p); } } } cout<<sum-cost[n][(cur+1)/2]<<" "<<dp[n][(cur+1)/2]<<"\n"; } return 0; }
优化之后:
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> #include<iostream> #define inf 1<<30 using namespace std; typedef long long ll; struct node{ int p,w; bool operator<(const node& a)const{ return p>a.p||(p==a.p&&w<a.w); } }nod[1002]; int dp[1002],cost[1002],t,n; string s; int main(){ cin>>t; while(t--){ int sum=0; memset(dp,0,sizeof dp); fill(cost,cost+1001,inf); cin>>n>>s; for(int i=1;i<=n;i++) cin>>nod[i].p>>nod[i].w,sum+=nod[i].p; sort(nod+1,nod+n+1); int cur=0; cost[0]=0; for(int i=s[0]=='P'?2:1;i<=n;i++){ cur++; for(int j=(cur+1)/2;j>=1;j--){//背包容量,每个物品的容量是1 if(dp[j-1]+nod[i].w>dp[j]){ dp[j]=dp[j-1]+nod[i].w; cost[j]=cost[j-1]+nod[i].p; }else if(dp[j-1]+nod[i].w==dp[j]){ cost[j]=min(cost[j],cost[j-1]+nod[i].p); } } } cout<<sum-cost[(cur+1)/2]<<" "<<dp[(cur+1)/2]<<"\n"; } return 0; }