AcWing 1022. 宠物小精灵之收服


题目传送门

一、题目解析

不是典型的\(01\)背包问题,而是一个二维费用的背包问题
花费1:精灵球数量
花费2:皮卡丘体力值
价值:小精灵的数量 每一个精灵的价值为\(1\)

二、实现代码

#include 

using namespace std;

const int N = 1010; //野生小精灵的数量上限
const int M = 510;  //小智的精灵球数量上限
int n;              //野生小精灵的数量
int m;              //小智的精灵球数(初始体积1)
int t;              //皮卡丘初始的体力值(初始体积2)
int f[N][M];        //打表数组

int v1[N];          //记录每个小精灵需要消耗的精灵球数量
int v2[N];          //记录每个小精灵需要消耗的皮卡丘体力值

int main() {
    //读入初始体积1和初始体积2,还有一个野生小精灵的数量
    cin >> m >> t >> n;

    //01背包套路
    for (int i = 1; i <= n; i++) { //逐个讨论每个小精灵
        //读入收服当前小精灵需要花费的精灵球数量和消耗的皮卡丘体力值
        cin >> v1[i] >> v2[i];
        //一维容量从高到低
        for (int j = m; j >= v1[i]; j--)
            //二维容量从高到低,需要注意的是皮卡丘的体力值最后不能为零~~~
            for (int k = t - 1; k >= v2[i]; k--)
                f[j][k] = max(f[j][k], f[j - v1[i]][k - v2[i]] + 1);
    }
    //输出最优个数解
    printf("%d ", f[m][t - 1]);
    //找到满足最大价值的所有状态里,第二维费用消耗最少的
    int k = 0;
    while (f[m][k] != f[m][t - 1]) k++;
    //皮卡丘的剩余体力值
    printf("%d", t - k);
    return 0;
}