• A. Acing the contestA. Acing the contest 状压DP + 思维


    A. Acing the contest 状压DP + 思维

    题目大意:

    (T) 个人参加比赛,你可以任意调换这个 (T) 个人参加比赛的顺序,每个人有生命值。
    (P) 个比赛,每个比赛有难度值 (b) 和奖励值 (c)。一个人可以选择参加这个比赛,减少 (b) 的生命值(要保证生命值最后非负),获得 (c) 的奖励。或者跳过这个比赛,或者将这个比赛甩手给下一个人。
    求最后得到的奖励值和最大值。

    题解:

    • (dp[s][i]) 表示的是现在的状态是 (s) ,现在已经解决到问题 (i) 了的最优解
    • 转移方程是: (dp[nxt][j] = max(dp[nxt][i],dp[cur][j]+解决到 i 到 j 问题的最优解))
    • (val[i][j][k]) 表示解决问题 (i)(j) ,花费生命值为 (k) 的最优解
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll dp[1<<11][110],val[110][110][110];
    /*
     * dp[s][i] 表示现在写题了的人的状态是 s,i 表示现在以及写到了第 i 个题目
     * val[i][j][k] 表示从 i 到 j 个问题,花费 k 个生命值的最优解
     */
    int e[11],d[110],s[110];
    int main() {
        int t, p;
        scanf("%d%d", &t, &p);
        for (int i = 1; i <= t; i++) scanf("%d", &e[i]);
        for (int i = 1; i <= p; i++) scanf("%d", &d[i]);
        for (int i = 1; i <= p; i++) scanf("%d", &s[i]);
        for (int i = 1; i <= p; i++) {
            for (int j = i; j <= p; j++) {
                for (int k = 1; k <= 100; k++) {
                    val[i][j][k] = max(val[i][j][k], val[i][j - 1][k]);
                    if (k >= d[j]) val[i][j][k] = max(val[i][j][k], val[i][j - 1][k - d[j]] + s[j]);
    //                if(k<=3)printf("val[%d][%d][%d]=%lld
    ",i,j,k,val[i][j][k]);
                }
            }
        }
        memset(dp, 0xef, sizeof(dp));
        dp[0][0] = 0;
        ll ans = 0;
        int sum = 1 << t;
        for (int cur = 0; cur < sum; cur++) {
            for (int i = 1; i <= t; i++) {
                int tmp = 1 << (i - 1);
                if (tmp & cur) continue;
                for (int j = 1; j <= p; j++) {
                    if (dp[cur][j - 1] < 0) continue;
                    for (int k = j; k <= p; k++) {
                        dp[cur | tmp][k] = max(dp[cur | tmp][k], dp[cur][j - 1] + val[j][k][e[i]]);
                        ans = max(ans, dp[cur | tmp][k]);
                    }
                }
            }
        }
        printf("%lld
    ", ans);
        return 0;
    }
    /*
    5 14
    3 3 3 3 3
    1 1 1 3 1 2 3 4 1 1 1 3 10 2
    10 9 8 30 21 22 50 100 10 10 10 32 100 2
     */
    
  • 相关阅读:
    盛最多水的容器
    除自身以外数组的乘积
    组合总和
    旋转图像
    找到所有数组中消失的数字
    RSA加密、签名机制
    SpringBoot-从新建一个项目看起
    linux下vi命令修改文件及保存的使用方法
    集合
    第一个注解式的SpringMVC项目
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/14482686.html
Copyright © 2020-2023  润新知