• 2159 ACM 杭电 杀怪 二维费用的背包+完全背包问题


    这里写图片描述
    题意:已知经验值,保留的忍耐度,怪的种数和最多的杀怪数。求进入下一级的最优方案。
    思路:用二维费用的背包+完全背包问题 (顺序循环)方法求解

    什么是二维费用的背包问题?
    问题:
    二维费用的背包问题是指:对于每件物品,具有两种不同的费用;选择这件物品必须同时付出这两种代价;对于每种代价都有一个可付出的最大值(背包容量)。问怎样选择物品可以得到最大的价值。设这两种代价分别为代价1和代价2,第i件物品所需的两种代价分别为a[i]和b[i]。两种代价可付出的最大值(两种背包容量)分别为V和U。物品的价值为w[i]。
    算法:
    费用加了一维,只需状态也加一维即可。设f[i][v][u]表示前i件物品付出两种代价分别为v和u时可获得的最大价值。状态转移方程就是:
    f[i][v][u]=max{f[i-1][v][u],f[i-1][v-a[i]][u-b[i]]+w[i]}
    可以只使用二维的数组:

    f[v][u]=max{f[v][u],f[v-a[i]][u-[b[i]]+w[i]}

    本题中的两个代价?
    1 忍耐度
    2 杀死怪兽的个数
    注意:代价不必用完,本题中容忍度不必用完,但是f[u][v]还是求的是最大值。

    本题:
    dp[i][j] = max (dp[i][j], dp[i - cos[f]][j - 1] + exp[f])
    杀死第j个妖怪,在忍耐度为i的情况下,获得的最大经验值。
    杀死第k种妖怪,得到经验值:exp,失去忍耐度,cos.
    注意:
    1 三个for循环都是顺循环(01背包第二个for是逆向循环),第二个for中要令int i = cos[f];不然结果回出错。
    2 最后扫的时候 因为题目要求出剩余忍耐度最大,没有约束必须用完忍耐度,一旦找到经验加满的即为最优解;所以忍耐度从1到m遍历dp.

    #include<stdio.h>
    #include<string.h>
    #define N 105
    #define max(a,b) a>b?a:b
    
    int main()
    {//nm,k,s(0 < n,m,k,s < 100)四个正整数。分别表示还需的经验值,保留的忍耐度,怪的种数和最多的杀怪数。
    
        int n, m, k, s, dp[N][N], exp[N], cos[N];
        while (scanf ("%d%d%d%d", &n, &m, &k, &s)!=EOF)
        {
            memset (dp, 0, sizeof (dp));
            for (int i = 1; i <= k; ++i)
                scanf ("%d%d", &exp[i], &cos[i]);
    
            for (int f = 1; f <= k; f++)
                for (int i = cos[f]; i <= m; ++i)
                    for (int j = 1; j <= s; ++j)
                        dp[i][j] = max (dp[i][j], dp[i - cos[f]][j - 1] + exp[f]);
            int i;
            for (i = 1; i <= m; ++i)
                if (dp[i][s] >= n)
                    break;
            if (i <= m) printf ("%d
    ", m - i);
            else printf ("-1
    ");
        }
    }
  • 相关阅读:
    GitLab-添加SSH Key亲历教程
    java-数组Array的应用总结
    Java-方法的重载和重写
    JSON-相关的工具收藏分享
    java-无重复的排列组合小技能
    Charles安装与使用
    深拷贝浅拷贝
    文件操作
    列表生成式
    非空即真,非零即真
  • 原文地址:https://www.cnblogs.com/CheeseIce/p/9588696.html
Copyright © 2020-2023  润新知