AtCoder Beginner Contest 145 E - All-you-can-eat ###K ###K //K
题目链接:https://atcoder.jp/contests/abc145/tasks/abc145_e
题意:有n道菜,每道菜需要a[i]分吃完,能获得b[i]的美味值 给T分钟,问怎么样吃,才能在T内得到最多的美味值,
一旦开始了吃就一定会吃完这道菜,哪怕时间超过T分
思路:很明显的01背包问题,不过是多了一个 某一道菜不受时间限制 的条件 很容易看出这里的一个 贪心就是 用1分钟给一道菜 这样是最优解
那么 此时的T就变为T-1 然后考虑01背包dp
加一维的空间满足 他有没有用上这 1分钟的条件 ,1为有 0为没有
关键的转移是 在x等于1的时候也要 用上
if(j>=w[i])
{
dp[i][j][x]=max(dp[i][j][x],dp[i-1][j-w[i]][x]+v[i]);
} 当已经使用了这个条件后, 此时就和0 的时候是等价的 ,剩下的也是转换为取和不取的问题, 否则 的话 1的状态无法延续下去
二维01背包的代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int maxn =1e6+10; 6 const int mod=998244353; 7 int w[3010]; 8 int v[3010]; 9 int dp[3010][3010][2]; 10 11 12 13 int main() 14 { 15 ios::sync_with_stdio(false); 16 cin.tie(0); 17 int n,t; 18 cin>>n>>t; 19 t--; 20 for(int i=1;i<=n;i++) 21 cin>>w[i]>>v[i]; 22 //int ans=0; 23 for(int i=1;i<=n;i++) 24 { 25 for(int j=0;j<=t;j++) 26 { 27 dp[i][j][0]=dp[i-1][j][0]; 28 dp[i][j][1]=max(dp[i-1][j][1],dp[i-1][j][0]+v[i]); 29 if(j>=w[i]) 30 { 31 dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-w[i]][0]+v[i]); 32 dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-w[i]][1]+v[i]); 33 } 34 //ans=max({ans,dp[i][j][0],dp[i][j][1]}); 35 } 36 } 37 cout<<dp[n][t][1]<<'\n'; 38 39 40 41 42 }
也可以优化成一维01背包的代码
要注意的是 先 更新1 在更新0 不然会重复拿同一样东西 因为1的时候要通过0来更新 当然逆序是肯定的
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int maxn =1e6+10; 6 const int mod=998244353; 7 int w[3010]; 8 int v[3010]; 9 int dp[3010][2]; 10 11 12 13 int main() 14 { 15 ios::sync_with_stdio(false); 16 cin.tie(0); 17 int n,t; 18 cin>>n>>t; 19 t--; 20 for(int i=1;i<=n;i++) 21 cin>>w[i]>>v[i]; 22 for(int i=1;i<=n;i++) 23 { 24 for(int j=t;j>=0;j--) 25 { 26 dp[j][1]=max(dp[j][1],dp[j][0]+v[i]); 27 if(j>=w[i]) 28 { 29 dp[j][1]=max(dp[j][1],dp[j-w[i]][1]+v[i]); 30 dp[j][0]=max(dp[j][0],dp[j-w[i]][0]+v[i]); 31 } 32 } 33 } 34 cout<<dp[t][1]<<'\n'; 35 36 37 38 39 }

浙公网安备 33010602011771号