洛谷题单指南-动态规划1-P1802 5 倍经验日

原题链接:https://www.luogu.com.cn/problem/P1802

题意解读:x个药取打n个怪,打赢打输都有经验,计算最大的经验数,跟01背包类似,可以理解为一个物品装得下或者装不下都可以装,装得下获得的价值高,装不下获得的价值低。

解题思路:

设lose[N], win[N], use[N]表示失败时获得的经验,胜利时获得的经验和打过要至少使用的药数量;

设dp[i][j]表示用j个药打前i个怪所能获得的最大经验;

当j >= use[i]时,可以选择打赢或者打输dp[i][j] = max(dp[i-1][j] + lose[i], dp[i-1][j-use[i]] + win[i]),注意打输是dp[i-1][j] + lose[i],j优先用来打前i-1,剩下的再对i打输,这样才是最优;

当j < use[i]时,只能打输,把药优先打前i-1个怪,dp[i][j] = dp[i-1][j] + lose[i]。

100分代码(二维):

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

const int N = 1005;
int n, x;
int lose[N], win[N], use[N];
int dp[N][N]; //dp[i][j]表示前i个人j个药能获得的最大经验

int main()
{
    cin >> n >> x;
    for(int i = 1; i <= n; i++) cin >> lose[i] >> win[i] >> use[i];
    for(int i = 1; i <= n; i++)
    {
        for(int j = 0; j <= x; j++)
        {
            dp[i][j] = dp[i-1][j] + lose[i]; //药剂j不够打i,只能打败
            if(j >= use[i]) dp[i][j] = max(dp[i][j], dp[i-1][j-use[i]] + win[i]); //药剂j够打i,可以打赢或者打输
        }
    }
    cout << 5ll * dp[n][x] << endl;
    return 0;
}

100分代码(一维):

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

const int N = 1005;
int n, x;
int lose[N], win[N], use[N];
int dp[N]; //dp[j]表示j个药能获得的最大经验

int main()
{
    cin >> n >> x;
    for(int i = 1; i <= n; i++) cin >> lose[i] >> win[i] >> use[i];
    for(int i = 1; i <= n; i++)
    {
        for(int j = x; j >= 0; j--)
        {
            if(j >= use[i]) dp[j] = max(dp[j] + lose[i], dp[j-use[i]] + win[i]); //药剂j够打i,可以打赢或者打输
            else dp[j] += lose[i]; //药剂j不够打i,只能打败
        }
    }
    cout << 5ll * dp[x] << endl;
    return 0;
}

 

posted @ 2024-04-19 10:42  五月江城  阅读(35)  评论(0编辑  收藏  举报