【2021年CCPC河南省赛】【DP】E. 简单游戏

2829: 闯关游戏

题意:

在这里插入图片描述
题解:2021CCPC河南省赛 E:闯关游戏(简单DP)

思路:

看起来像是分组背包题,但是一旦往分组背包方向想就会寄。因为分组背包是每一组最多选一个,而这个题是必须选一个,所以还是要自己推一个 DP 公式。

定义 d p [ i ] [ j ] dp[i][j] dp[i][j] 为前 i i i 关花费恰好是 j j j 的最大价值,那么初始 d p [ 0 ] [ 0 dp[0][0 dp[0][0 ~ m ] = 0 , − 1 , − 1 , − 1 ⋯ − 1 m]={0, -1, -1,-1 \dots -1} m]=0,1,1,11 ,-1 代表是无效状态,不能推到其他的状态。转移方程就是 d p [ i ] [ j ] = max ⁡ ( d p [ i − 1 ] [ j − v ] + w ) ( 当 d p [ i − 1 ] [ j − v ] ! = − 1 时 ) dp[i][j]=\max(dp[i-1][j-v]+w)(当dp[i-1][j-v]!=-1时) dp[i][j]=max(dp[i1][jv]+w)(dp[i1][jv]!=1)

另外 d p [ i ] [ j ] dp[i][j] dp[i][j] 也可以定义成前 i i i 关花费上限是 j j j 的最大价值。

AC代码:http://acm.zzuli.edu.cn/showsource.php?id=6206359

#include<bits/stdc++.h>
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
#define endl '\n'
#define fi first
#define se second
#define ppb pop_back
#define pb push_back
#define ios ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
 
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define mset(x, a) memset(x, a, sizeof (x))
#define rep(i, l, r) for(LL i = l; i <= (r); ++ i)
#define per(i, r, l) for(LL i = r; i >= (l); -- i)
#define reps(i, l, r, d) for(LL i = l; i <= (r); i += d)
#define pers(i, r, l, d) for(LL i = r; i >= (l); i -= d)
 
template<class T> bool ckmax(T& a, T b) { return a < b ? (a = b, 1) : 0; }
template<class T> bool ckmin(T& a, T b) { return a > b ? (a = b, 1) : 0; }
 
const int N = 2e5 + 10, M = 1e5 + 10;
const LL p = 1e9 + 7;
const LL inf = 0x3f3f3f3f3f3f3f3f;
 
LL n, h, dp[2][N];
 
void solve()
{
    cin >> n >> h;
    LL ans = 0;
    rep(i, 0, h) dp[0][i] = dp[1][i] = -1;
    dp[0][0] = 0;
    rep(i, 1, n){
        LL a, b, c, d; cin >> a >> b >> c >> d;
        rep(j, 0, h){
            dp[i & 1][j] = -1;
            if(j - a >= 0 && dp[i + 1 & 1][j - a] != -1) ckmax(dp[i & 1][j], dp[i + 1 & 1][j - a] + b);
            if(j - c >= 0 && dp[i + 1 & 1][j - c] != -1) ckmax(dp[i & 1][j], dp[i + 1 & 1][j - c] + d);
            ckmax(ans, dp[i & 1][j]);
        }
    }
    cout << ans << endl;
}
 
int main()
{
 
    ios;
 
    int T; cin >> T;
    while(T -- )
        solve();
 
 
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值