http://poj.org/problem?id=2063
题意:Jone想做一笔投资。现在他有一笔初始资金,准备做几年的投资。他想买债券,债券的归还期为一年,也就是说每到一年他得回收本金与利息,再次购买新的债券。债券有n种,每种的价格和利息(每年)都列举出来。求最大收益。
ps:好难懂的题意,不过很贴近于生活。
思路:由于想买的债券每种都是无限数量,所以是完全背包求不超过每年初始资金的最大利息。由于债券可以被1000整除,所以背包中原始资金的容量也应该除以1000。这里dp的最大范围比较难算,1 000 000/1000=1000后每年利息不超过10%,也就是说40年后至少也有100*40=4000的利息,不过以防万一,还是尽量往大开好了。这里RE了一次。另外,这题背包是未装满,初始dp为0。还有,用二维的话会爆内存,所以一般情况还是能用一维就用一维吧。
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 46005;
const int INF = 0x3f3f3f3f;
int dp[N];
int main()
{
// freopen("in.txt", "r", stdin);
int t, V, n, time;
int cost[N], weight[N];
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &V, &time);
scanf("%d", &n);//物品数量
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &cost[i], &weight[i]);
cost[i]/=1000;
}
int V0 = V;
int inte = 0;//利息
for(int k = 1; k <= time; k++)
{
memset(dp, 0, sizeof(dp));//未装满
V += inte;
V0 = V/1000;
for(int i = 1; i <= n; i++)
for(int j = cost[i]; j <= V0; j++)
{
dp[j] = max(dp[j], dp[j-cost[i]]+weight[i]);
}
inte = dp[V0];
}
printf("%d\n", V+inte);
}
return 0;
}
想了想还是把爆内存的二维贴上来吧。
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 4600;
const int INF = 0x3f3f3f3f;
int dp[N][N];
int main()
{
// freopen("in.txt", "r", stdin);
int t, V, n, time;
int cost[N], weight[N];
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &V, &time);
scanf("%d", &n);//物品数量
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &cost[i], &weight[i]);
cost[i]/=1000;
}
int V0 = V;
int inte = 0;//利息
for(int k = 1; k <= time; k++)
{
memset(dp, 0, sizeof(dp));//未装满
V += inte;
V0 = V/1000;
for(int i = 1; i <= n; i++)
for(int j = 0; j <= V0; j++)
{
if(j < cost[i]) dp[i][j] = dp[i-1][j];
else dp[i][j] = max(dp[i-1][j], dp[i][j-cost[i]]+weight[i]);
}
inte = dp[n][V0];
printf("[%d]\n", inte);
}
printf("%d\n", V+inte);
}
return 0;
}