【dp】Day 3 提高组模拟C组 T2 电视游戏问题

题目链接

https://www.luogu.org/problemnew/show/P2967

题目大意

n 件平台,有 m 元钱,每件平台都有一定的代价,购买这个平台就可以获得某些游戏的使用权,但是要玩这些游戏还需要花费一定的代价,但也可以获得一定的价值
求不大于 m 元钱的最大价值

解题思路

这道题明显是金明的预算方案的加强版,对于多种情况我们需要分类讨论
1. 不选该平台
2. 选该平台

对于第二种操作,我们还需要再进行一次0/1背包

  1. 选该游戏
  2. 不选该游戏

    所以,我们就得到了下面这些
    f [ i ] [ j ] 表示前 i 个平台,花费了 j 元钱的最大价值,对于不选平台操作,我们可以少花 j 元钱,所以得到下面这个方程

    f [ i ] [ j ] = f [ i 1 ] [ j ]

    对于选该平台操作,我们需要进行一波0/1背包,无非选或不选,得到下面方程
    f [ i ] [ j + ] = m a x { f [ i 1 ] [ j ] + }

然后取这两种方案最大值即可

这样子做的空间消耗为 O ( n m ) 会爆炸,所以需要压缩数组,可以发现 f [ i ] 只与 f [ i 1 ] 有关系,所以可以滚动压缩

代码

#include<cstdio>
using namespace std;int n,m,f[1000010],f2[1000010],gs,dj,num1,num2;
int main()
{
    freopen("vidgame.in","r",stdin);
    freopen("vidgame.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i =0;i<n;++i)
    {
        scanf("%d %d",&dj, &gs);
        for (int j=dj;j<=m;j++)f2[j]=f[j-dj];//不选该平台
        for (int j=0;j<gs;++j) 
        {
            scanf("%d%d",&num1,&num2);
            for (int j=m-num1;j>=dj;j--) //选该平台
                if (f2[j+num1]<f2[j]+num2) f2[j+num1]=f2[j]+num2;//选该游戏
        }
        for (int j=dj;j<=m;j++) if (f[j]<f2[j]) f[j]=f2[j];//保存最大值
    }
    printf("%d",f[m]);
}

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/80960171
今日推荐