USACO Video Game Troubles

BNUOJ 4140

有很多游戏平台,每个平台上有很多游戏,每个游戏有花费和价值。

这道题很有趣,要背包两次,先考虑要不要买某个游戏,再考虑要不要买某个游戏平台。

看了这个题解才明白的:http://blog.sina.com.cn/s/blog_4a0c4e5d010147j3.html

循环过每个平台所有游戏之后,再考虑购买游戏平台的花费,这时候转换为另一个背包问题,要不要买这个平台。

dp[j][k] 表示第i个(当前平台)考虑了j个游戏,预算为k时的最大价值。dp[0][k] 就是前i个平台,当前预算为k的最优值。。


#include 
#include 
#include 
using namespace std;
const int MAXN = 55;
const int MAXG = 15;
int p[MAXN];
int g[MAXN];
int gp[MAXN][MAXG], pv[MAXN][MAXG];
int dp[MAXN][100010];
int main()
{
    int n, v;
    while (scanf("%d%d", &n;, &v;)!=EOF)
    {
        memset(dp, 0, sizeof(dp));
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &p;[i]);
            scanf("%d", &g;[i]);
            for (int j = 1; j <= g[i]; j++)
            {
                scanf("%d%d", &gp;[i][j], &pv;[i][j]);
            }
        }
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= g[i]; j++)
            {
                for (int k = v; k >= 0; k--)
                {
                    if (k >= gp[i][j]) dp[j][k] = max(dp[j-1][k], dp[j-1][k-gp[i][j]] + pv[i][j]);
                    else dp[j][k] = dp[j-1][k];
                }
            }

            for (int k = v; k >= p[i]; k--)
            {
                dp[0][k] = max(dp[0][k], dp[g[i]][k-p[i]]);
            }
        }
        printf("%d\n", dp[0][v]);
    }
    return 0;
}


comments powered by Disqus