Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/65536 K (Java/Others)
Total Submission(s): 174 Accepted Submission(s): 92
3 800 300 2 30 50 25 80 600 1 50 130 400 3 40 70 30 40 35 60
210
USACO DEC09 Problem 'vidgame' Analysis
by Alex Schwendner
这是一个动态规划的问题。
不考虑需要购买游戏机,这就是一个背包问题,游戏价格GP_j是大小,产生价值PV_j是该背包所求的价值,预算V则是背包的大小。如果我们不管购买游戏机,我们可以定义prod[j][c]是我们选择到第j个游戏和总花费为c美元时的最大价值。这样可以推导出:
prod[j][c] = max(prod[j-1][c], PV_j + prod[j-1][c - GP_j])
对于每个新的游戏j,我们可以不买它,或者我们可以花费GP_j元买它,并得到一个PV_j的价值。然后,请注意一旦我们购买了一个游戏机i,那么选择游戏机i上能够玩的游戏也就变成了一个简单的背包,我们仍可以通过以上的方法解决。也就是说,对于给定的游戏机i,我们计算出游戏机i上能玩的所有游戏的prod[j][c],这就告诉我们对于每一个预算我们应该购买哪些能在游戏机i上玩的游戏。
最后一步,我们选择需要购买的游戏机。将问题考虑为一个关于购买游戏机的背包问题,不过每一个游戏机并不是只有单一的成本和价值:
我们花在每一个游戏机上的费用,取决于我们所购买游戏和相应价值的多少。对于游戏机i的每一个prod[j][c]表示我们可以购买的不同的“游戏机i组合包”。在循环到i时,我们可以选择购买游戏机i和其中一个“游戏机i组合包”,或者我们可以直接跳过这个游戏机i。这样问题就分解了一个关于游戏机的背包程序,以及计算每一个游戏机i所有prod[j][c]的背包子程序。当我们就完成了这个动态规划后,就得到了对于所有游戏机的最优值。
HDU3449代码
#include<cstdio> #include<algorithm> using namespace std; int main() { int j,k,n,m,V,p0,p,v; while(scanf("%d%d",&n,&V)==2) { int d[100005]={0},dp[100005]={0}; while(n--) { scanf("%d%d",&p0,&m); for(j=p0;j<=V;j++) dp[j]=d[j-p0]; while(m--) { scanf("%d%d",&p,&v); for(k=V-p;k>=p0;k--) dp[k+p]=max(dp[k+p],dp[k]+v); } for(j=p0;j<=V;j++) d[j]=max(d[j],dp[j]); } printf("%d/n",d[V]); } }