RQNOJ 671 纯洁的买卖:无限背包
题目链接:https://www.rqnoj.cn/problem/671
题意:
ALEJ要通过倒卖东西来赚钱。
现在他有m元经费。
有n种物品供他选择,每种物品数量无限。
第i件物品的买入价为c[i],卖出价为r[i],每卖出一件物品i后,要交c[i]的税。
问:一次买卖之后,经费最多有多少。
题解:
注:(1)“买”和“卖”是有顺序的。
也就是说,收购一件物品所得到的“未来利润”并不能当作现在的经费来用。
(2)“缴税”是在卖东西的时候,收购的时候并不会在经费中扣除税(c[i])。
相当于从“未来利润”中扣除c[i]
表示状态:
dp[i][j] = max wealth(未来利润)
i:考虑到第i种物品
j:当前花的经费
找出答案:
max dp[i][j] - j
如何转移:
无限背包,正着枚举j。
花费为c[i],价值为w[i] - c[i]。
dp[i][j] = max(dp[i-1][j], dp[i-1][j-c[i]] + w[i])
边界条件:
dp[0][0] = m
others = -1
AC Code:
1 // state expression: 2 // dp[i][j] = max wealth 3 // i: considering ith goods 4 // j: present cost 5 // 6 // find the answer: 7 // max dp[i][j] - j 8 // 9 // transferring: 10 // dp[i][j] = max(dp[i-1][j], dp[i-1][j-c[i]] + w[i]) 11 // 12 // boundary: 13 // dp[0][0] = m 14 // others = -1 15 #include <iostream> 16 #include <stdio.h> 17 #include <string.h> 18 #define MAX_N 105 19 #define MAX_M 1000005 20 21 using namespace std; 22 23 int n,m; 24 int ans; 25 int c[MAX_N]; 26 int w[MAX_N]; 27 int dp[MAX_M]; 28 29 void read() 30 { 31 cin>>n>>m; 32 for(int i=0;i<n;i++) 33 { 34 cin>>c[i]>>w[i]; 35 } 36 } 37 38 void solve() 39 { 40 ans=m; 41 memset(dp,-1,sizeof(dp)); 42 dp[0]=m; 43 for(int i=0;i<n;i++) 44 { 45 for(int j=0;j<=m;j++) 46 { 47 if(j-c[i]>=0 && dp[j-c[i]]!=-1) 48 { 49 dp[j]=max(dp[j],dp[j-c[i]]+w[i]-c[i]); 50 } 51 ans=max(ans,dp[j]-j); 52 } 53 } 54 } 55 56 void print() 57 { 58 cout<<ans<<endl; 59 } 60 61 int main() 62 { 63 read(); 64 solve(); 65 print(); 66 }