POJ 2063 Investment 滚动数组+完全背包
题目链接:
http://poj.org/problem?id=2063
题意:
你现在有现金m元,你要做n年的存款投资,给你k种投资方式,每种需要现金vi元,能获得xi元的理论,一年到期后你要利用拿到的本息和重新投资,问这样做n年最后能拿到的最大本息和是多少。
题解:
dp[i]表示你花i元去投资能获得的最大利润。
则第一年你要做的就是dp[1]->dp[m](m为初始金额) 假设获得的最大奖金为m_inte[i];
则第二年要做的是dp[m+1]->dp[m+m_inte[i]]
...
这样,完全背包一直做n年就可以了。
由于dp数组最多只能开到7*10^6(30000kb),所以这里用滚动数组的方式来节约空间,否则会爆空间限制。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 const int maxn = 1e6+10; 8 const int mod = maxn; 9 10 int n; 11 int mny, ye; 12 int valu[11], inte[11]; 13 int dp[maxn]; 14 15 void init() { 16 memset(dp, -1, sizeof(dp)); 17 } 18 19 int main() { 20 int tc; 21 scanf("%d", &tc); 22 while (tc--) { 23 init(); 24 scanf("%d%d", &mny, &ye); 25 scanf("%d", &n); 26 for (int i = 0; i < n; i++) scanf("%d%d", valu + i, inte + i); 27 int idx = 1000; dp[0] = 0; 28 int ans = 0; 29 while (ye--) { 30 for (; idx <= mny; idx += 1000) { 31 dp[idx%mod] = -1; 32 for (int i = 0; i < n; i++) { 33 if (idx - valu[i] < 0) continue; 34 if (dp[(idx - valu[i])%mod]!=-1) { 35 dp[idx%mod] = max(dp[idx%mod], dp[(idx - valu[i])%mod] + inte[i]); 36 ans = max(ans, dp[idx%mod]); 37 } 38 } 39 } 40 mny += ans; 41 } 42 printf("%d\n", mny); 43 } 44 return 0; 45 }