[LOJ6217] 扑克牌

Description

给定一摞扑克牌,共 (n le 1000) 张,每张牌有两个属性 (a_i,b_i le 1000)。可以无限次进行以下两种操作:①对于堆顶的牌 ((a,b)),从上到下扔掉 (a) 张牌,得分 (+b);②将牌堆顶的牌放到底部。求能获得的最大得分。

Solution

连续拿走若干张牌的条件,和随意拿走若干张牌,其实是等价的。

证明:反证法,考虑不等价,即连续拿走 (x) 时必须拿走 (y),但是 (y) 是想要另拿的。此时若我们可以先把 (y) 拿掉则矛盾。若我们不可以先拿走 (y),那么一定有 (a_x+a_y >n),则此时不可能在不连续情况下另拿 (y),故矛盾。

于是问题转化为,总空间为 (n) 的背包,每种物品占用空间 (a_i),价值为 (b_i),求最大价值。

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1005;

int n,a[N],b[N],f[N];

signed main()
{
    ios::sync_with_stdio(false);

    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i]>>b[i];
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=n;j>=a[i];j--)
        {
            f[j]=max(f[j],f[j-a[i]]+b[i]);
        }
    }

    cout<<*max_element(f,f+n+1);
}

原文地址:https://www.cnblogs.com/mollnn/p/13668935.html