题解 | #购物单#

购物单

https://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4

#include <algorithm>
#include <array>
#include <iostream>
#include <list>
#include <vector>
using namespace std;
const int N = 32000/10 + 1;
const int M = 60 + 1;
int m, n;
//表示购买1,或者不购买0该物品下的最大满意 w[i][j][k]表示买0件主物品,:j中,有k钱的最大满意
std::array< std::array<std::array<int, N>, M>, 2>  W;
std::array<std::vector<int>,M> step_; //决策步
std::vector<int> step; //更简单的决策步

int main() {
    cin >> n >> m;
    n /= 10;
    std::array<std::array<int, 3>, M>  vpq; //vpq
    int v, p, q;
    //输入
    for (int i = 1; i <= m; i++) {
        cin >> v >> p >> q;
        //cout<<i<<" "<<v<<" "<<p<<" "<<q<<endl;
        vpq[i][0] = v/10;
        vpq[i][1] = p*v;
        vpq[i][2] = q;
        if (q == 0) {
            step_[i].insert(step_[i].begin(),i);
        } else {
            step_[q].push_back(i);
        }
    }
    //决策步
    for (std::vector<int> v:step_){
        if (v.size() && vpq[v.front()][2]!=0){//考虑到没有主
            continue;
        }
        for (int i:v){
            step.push_back(i);
        }
    }
    //动态规划
    for (int i = 0; i < step.size(); i++) { //物品
            int x = step[i];
            int v = vpq[x][0]; //价格
            int w = vpq[x][1]; //满意度
            //找到前一个
            int y = -1;
            bool isman = vpq[x][2]==0;
            for (int j = 0; j <= n; j++) { //cost
                if (i != 0) { //存在前驱
                    y = y = step[i-1];
                    if (j < v) { //买不起

                        W[0][x][j] = std::max(W[0][y][j], W[1][y][j]);
                        W[1][x][j] = -1;
                    } else { //买得起
                        if (isman) { //主
                            //cout<<y<<endl;
                            W[0][x][j] = std::max(W[0][y][j], W[1][y][j]);
                            W[1][x][j] = std::max(W[0][y][j - v], W[1][y][j - v])+w;
                        } else {//附件
                            W[0][x][j] = W[0][y][j];
                            if (W[1][y][j-v]>=0){//合理
                                W[1][x][j] = std::max(W[1][y][j], W[1][y][j - v]+w);
                            }
                            else {
                                 W[1][x][j] = W[1][y][j];
                            }
                        }
                    }
                } else { //没有前驱
                    if (j < v) { //买不起
                        W[0][x][j] = 0;
                        W[1][x][j] = -1;
                    } else { //买得起
                        W[0][x][j] = 0;
                        W[1][x][j] = w;
                    }
                }
                //cout<<x<<" "<<j<<" "<<W[0][x][j]<<" "<<W[1][x][j]<<endl;
            }
        }
        cout<<std::max(W[0][step.back()][n],W[1][step.back()][n])<<endl;
    }
    
// 64 位输出请用 printf("%lld")

0-1背包问题上添加了约束,可以把主物品合配件视为一个整体,每步的选择从{0,1}变成了{{man},{man,1},{man,2},{man,1,2}},共

2^t种,t为附件数,总的时间复杂度为m*n*2^t.也可以把附件也视作物品,不过由于物品件的选择存在依赖关系,因此解的结构有变。具体如下:

在G∪{g}中选择的最大满意值 =

1.G的最大满意值

2.G的最大满意值+g的满意值

3.G含g主件的最大满意值+g的满意值

这里忽略了花费,3对应的是g为附件的情况,主件因为不受约束和0-1背包一致,可以和之前一样求出结果,我们在额外求一个选择(0-1中的1)了该主件的最大满意值,选择中增加附件也就可以求解了(从这里可以看到,主件要先求)。我在代码中写的两个表是1.G的含g主件最大满意值,2.G的不含g主件的最大满意值,是差不多的

全部评论

相关推荐

仁者伍敌:牛子这些人还会点一个自动回复,boss都不带回复的
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务