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
", mny);
43     }
44     return 0;
45 }
原文地址:https://www.cnblogs.com/fenice/p/5463134.html