蓝桥杯赛第10届省赛


#include

using namespace std;
const int N = 110;

struct Node {
    int weight; //重量
    int volume; //体积
    int money;  //让利金额
} a[N];

/**
 测试用例
 10 9 4
 8 3 6
 5 4 5
 3 7 7
 4 5 4
 */

//在取得最大让利金额的时候,到底是拿了哪些商品?
string s[N][N][N];

//三维数组用来装最大优惠结果集
int yh[N][N][N];

int main() {
    //w:可以提起 w 单位重量的东西,
    //v:有一个能装v个单位体积的购物袋
    //n:为商品种类数
    int w, v, n;
    cin >> w >> v >> n;
    for (int i = 1; i <= n; i++) cin >> a[i].weight >> a[i].volume >> a[i].money;

    //三维数组初始化
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= w; j++) {
            for (int k = 0; k <= v; k++) {
                yh[i][j][k] = 0;
                //初始化
                s[i][j][k] = "";
            }
        }
    }
    //遍历每个种类
    for (int i = 1; i <= n; i++) {
        //从1开始,一个一个去增加重量尝试
        for (int j = 1; j <= w; j++) {
            //从1开始,一个个去增加体积尝试
            for (int k = 1; k <= v; k++) {
                //yh[0]是没有意义的,就是为了数学好算,也就是在未引入i时的上一个最优解
                int bn = yh[i - 1][j][k];
                int x = 0;
                //如果剩余的重量和体积都够用的时候,尝试拿当前物品
                if (j >= a[i].weight && k >= a[i].volume) 
                    x = yh[i - 1][j - a[i].weight][k - a[i].volume] + a[i].money;
                
                if (x > bn) { //如果拿了比不拿价值大,就拿这个物品
                    yh[i][j][k] = x;
                    //同时记录拿了这个物品
                    s[i][j][k] = s[i - 1][j - a[i].weight][k - a[i].volume] + " " + (char) (i + '0');
                } else {
                    //否则记录当前重量和体积的最优策略是不拿
                    yh[i][j][k] = bn;
                    //同时记录不拿当前物品,保持和之前一样的物品列表
                    s[i][j][k] = s[i - 1][j][k];
                }
            }
        }
    }
    //输出
    cout << yh[n][w][v] << endl; //小惠能够得到的最大让利金额
    string str = s[n][w][v];     //依次为从小到大排列的商品序号
    cout << str.substr(1, str.size() - 1);
}