原题
题目分析
明显的01背包,但还是由细节需要处理,设置dp[i][j]=前i头牛中选的TF为j时最大的TS值,由于TF可能为负数因此要加一个基数使其在大于等于零,dp初始化为-1,dp[0][0]=0.更新的时候dp[i][j]=max(dp[i-1][j-f[i]]+s[i],dp[i-1][j]).观察这个dp的更新可以发现能状态压缩,当f[i]>=0时,j从大到小更新,当f[i]<0时,j从小到大更新.最后从基数往上扫dp[j]+j-基数的最大值就是答案,注意前提是dp[i]>=0.
代码
1 #include <iostream> 2 #include <algorithm> 3 #include <utility> 4 #include <cstdio> 5 #include <cmath> 6 #include <cstring> 7 #include <string> 8 #include <vector> 9 #include <stack> 10 #include <queue> 11 #include <map> 12 #include <set> 13 14 using namespace std; 15 typedef long long LL; 16 const int INF_INT=0x3f3f3f3f; 17 const LL INF_LL=0x3f3f3f3f3f3f3f3f; 18 19 struct N 20 { 21 int s,f; 22 }cow[200]; 23 int dp[300000]; 24 25 bool cmp(N a,N b) 26 { 27 return a.s>b.s; 28 } 29 30 int main() 31 { 32 // freopen("black.in","r",stdin); 33 // freopen("black.out","w",stdout); 34 int n; 35 cin>>n; 36 int uplimit=0,downlimit=0; 37 for(int i=1;i<=n;i++) 38 { 39 cin>>cow[i].s>>cow[i].f; 40 if(cow[i].f>0) uplimit+=cow[i].f; 41 else downlimit+=cow[i].f; 42 } 43 sort(cow+1,cow+n+1,cmp); 44 int limit=max(uplimit,abs(downlimit)); 45 /* printf("limit=%d\n",limit); 46 for(int i=1;i<=n;i++) printf("cow %d s %d f %d\n",i,cow[i].s,cow[i].f);*/ 47 for(int j=0;j<=2*limit;j++) dp[j]=-1*INF_INT; 48 dp[limit]=0; 49 for(int i=1;i<=n;i++) 50 { 51 if(cow[i].f>=0) 52 { 53 for(int j=2*limit;j>=0;j--) 54 { 55 int from=j-cow[i].f; 56 if(from>=0&&from<=limit*2&&dp[from]!=-1*INF_INT) 57 { 58 dp[j]=max(dp[j],dp[from]+cow[i].s); 59 } 60 } 61 } 62 else 63 { 64 for(int j=0;j<=2*limit;j++) 65 { 66 int from=j-cow[i].f; 67 if(from>=0&&from<=limit*2&&dp[from]!=-1*INF_INT) 68 { 69 dp[j]=max(dp[j],dp[from]+cow[i].s); 70 } 71 } 72 } 73 // for(int j=0;j<=2*limit;j++) if(dp[now][j]!=-1) printf("dp %d %d=%d\n",i,j-limit,dp[now][j]); 74 } 75 int ans=0; 76 for(int i=limit;i<=limit*2;i++) if(dp[i]>=0) ans=max(ans,dp[i]+i-limit); 77 cout<<ans<<endl; 78 return 0; 79 }
原文地址:https://www.cnblogs.com/VBEL/p/11415356.html
时间: 2024-11-05 17:30:10