POJ 2063 Investment(完全背包)
http://poj.org/problem?id=2063
题意:
初始时有m (m<=10000) 美元,如今有n仅仅股票,每仅仅股票如果购买一份的话当前的利润也给出了(能够无限购买). 如果你第一年用m美元买了股票,这年结束的时候你就会把全部股票原价卖出而且得到你全部股票的利润. 然后你又開始第2年股票的投资了...(股票的价格都是1000的整数倍,且每仅仅股票的年收益率<=10%)
如今你须要连续买t年(t<=40) 的股票, 问你t年后你的总钱数是多少.
分析:
因为有n仅仅股票且每仅仅股票能够无限买, 所以本题能够把每一年的投资看成是一个全然背包问题. 然后用前一年的利润+本钱继续进行下一年的投资(又是一个全然背包过程).
因为每年投资的本金到年尾还是能回来的,所以我们仅仅须要求出每年的最大利润就可以. 所以本题能够变成以下的问题:
你手上有m美元, 然后有n种物品你能够无限买, 每种物品具有不同的价格cost[i] 和价值val[i]. 如今你须要在花费<=m美元的前提下使得物品总价值sum_val最大?
上面就是一个标准的全然背包问题. 可是本题的m<=10000, 且股票收益最大可达10% 且最多投资40年, 所以10000*(1.1)^40 == 4500W左右. 我们不可能每轮都用dp[450000000]的数组去做的.
题目说了每一个股票价格都是1000的倍数, 而这里我们仅仅要求出一年用m美元能得到的最大利润就可以.所以我们把上面问题变成以下的问题:
初始你手里有m/1000 个资源(每一个资源代表1000美元) , 你有n种物品能够买, 每种物品须要cost[i]/1000个资源才干买 且 你能获得val[i]的价值, 问你最多能获得多少价值?
这样我们的数组仅仅要开dp[450000]就可以. 如今我们来解决一次全然背包问题.
令dp[i][j]==x 表用前i个物品在总花费<=j 时, 最多能获得价值x.
初始化: dp全0.
状态转移: dp[i][j] = max( dp[i-1][j] , dp[i][j-cost[i]]+val[i])
前者代表第i个物品一个都不买, 后者代表至少买1个第i个物品.
终于我们所求为 dp[n][m]. (这个就是本年最大利润)
在每轮投资的末尾, 把当年最大利润加到本金m上就得到了下一年開始时的本金数目了. 一共t年后就可以求得最后的最大金额.
AC代码:
#include<algorithm> #include<cstring> #include<cstdio> using namespace std; const int maxn=46000+5; int n;//共n种基金 int m;//初始m美元 int t;//须要买t年 int cost[10+5];//每种基金价格 x千美元 int val[10+5]; //每种基金年收益 x美元 int dp[maxn]; int main() { int T; scanf("%d",&T); while(T--) { //读输入数据 scanf("%d%d%d",&m,&t,&n); for(int i=1;i<=n;i++) { scanf("%d%d",&cost[i],&val[i]); cost[i]/=1000;//第i个股票须要cost[i]千美元来买 } //每年的处理过程 for(int loop=1;loop<=t;loop++) { int max_money=m/1000;//max_money是本年能用多少(千美元) memset(dp,0,sizeof(dp)); //递推过程 for(int i=1;i<=n;i++) { for(int j=cost[i];j<=max_money;j++) dp[j] = max(dp[j], dp[j-cost[i]]+val[i]); } m+=dp[max_money];//当年利润叠加到总金钱上 } //输出结果 printf("%d ",m); } return 0; }
版权声明:本文博主原创文章,博客,未经同意不得转载。