题解 | #购物单#

购物单

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

这个题好难,看B站视频学会的,官方讲解根本就不是给初学者看的。

一开始没有提前处理,把附件挂在主件下边,然后填dp数组时忽略附件。

我一开始是想给主件做个标记表示已经买过,后来发现会冲突,于是才使用现在的方法,也就是官方视频的方法。

#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
struct object {
    int price;//价格
    int val;//重要 1-5
    int belong;//属于x的附件
    int a1;
    int a2;
    void init(int a, int b, int c) {
        price = a;
        val = b;
        belong = c;
    }
    void seta1(int price){
        a1=price;
    }
    void seta2(int price){
        a2=price;
    }
};
int adjust(int& money, object* obj, int count) {
    int min = money;
    int res = 10;
    bool flag = false;
    for (int i = 1; i < count + 1; i++) {
        if (min > obj[i].price) {
            min = obj[i].price;
        }
    }
    obj[0].price = money;
    for (int i = 10; i <= min; i += 10) {
        flag = false;
        for (int j = 0; j < count + 1; j++) {
            if (obj[j].price % i != 0) {
                flag = true;
                break;
            }
        }
        if (flag)continue;
        res = i; //找到最小公因数
    }
    for (int i = 1; i < count + 1; i++) {
        obj[i].price = obj[i].price / res;
    }
    money = money / res; //化简输入
    return res;
}
int main() {
    int money, count; //总钱数,物品总数
    cin >> money >> count;
    int a, b, c;
    object obj[count + 1];
    memset(obj, 0, sizeof(obj));
    obj[0].init(0, 0, 0);
    for (int i = 1; i <= count; i++) {
        cin >> a >> b >> c;
        obj[i].init(a, b, c);
        if(c!=0){//把附件对应到主件
            if(obj[c].a1==0) obj[c].seta1(i);
            else if(obj[c].a2==0) obj[c].seta2(i);
        }
    }
    int rate = adjust(money, obj, count);//返回缩放比例
    int dp[count + 1][money + 1];
    memset(dp, 0, sizeof(dp));
    for (int row = 1; row < count + 1; row++) {
        int price[4];//0 主件 1 附件1 2 附件2 3 附件1加2
        int satisf[4];
        memset(price, 0, sizeof(price));
        memset(satisf, 0, sizeof(satisf));
        //只买主件
        price[0]=obj[row].price;
        satisf[0]=obj[row].price * obj[row].val;
        //买主件和附件1
        if(obj[row].a1>0){
            price[1]=obj[obj[row].a1].price + price[0];
            satisf[1]=obj[obj[row].a1].price * obj[obj[row].a1].val + satisf[0];
        }
        //买主件和附件2
        if(obj[row].a2>0){
            price[2]=obj[obj[row].a2].price + price[0];
            satisf[2]=obj[obj[row].a2].price * obj[obj[row].a2].val + satisf[0];
        }
        //买主件和两个附件
        if(obj[row].a1>0 && obj[row].a2>0)
        {
            price[3]=obj[obj[row].a1].price + obj[obj[row].a2].price + price[0];
            satisf[3]=obj[obj[row].a1].price * obj[obj[row].a1].val + obj[obj[row].a2].price * obj[obj[row].a2].val + satisf[0];
        }
        for (int col = 1; col < money + 1; col++) {
            if(obj[row].belong>0)//是附件
            {
                dp[row][col]=dp[row-1][col];//如果是附件,使用上一行结果
            }
            else 
            {
                if(col>=price[0] && price[0]!=0)//只买主件
                {
                    dp[row][col]=std::max({dp[row-1][col] , dp[row-1][col-price[0]] + satisf[0]});
                }
                else if(col<price[0])//是主件但是钱不够
                {
                    dp[row][col]=dp[row-1][col];
                }
                if(col>=price[1] && price[1]!=0)//买主件和附件1
                {
                    dp[row][col]=std::max({dp[row][col] , dp[row-1][col-price[1]] + satisf[1]});
                }
                if(col>=price[2] && price[2]!=0)//买主件和附件2
                {
                    dp[row][col]=std::max({dp[row][col] , dp[row-1][col-price[2]] + satisf[2]});
                }
                if(col>=price[3] && price[3]!=0)//买主件和附件1 和 附件2
                {
                    dp[row][col]=std::max({dp[row][col],
                                            dp[row-1][col-price[3]] + satisf[3], 
                                            dp[row-1][col-price[2]] + satisf[2],
                                            dp[row-1][col-price[1]] + satisf[1],
                                            dp[row-1][col-price[0]] + satisf[0]});
                }
            }
            //cout<<dp[row][col]<<' ';
        }
        //cout<<"\n";
    }
    cout << dp[count][money] * rate << endl;
}
// 64 位输出请用 printf("%lld")

全部评论

相关推荐

挥毫自在:想白嫖你呢
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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