题解 | #购物单#

购物单

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

#include <iostream>
#include <vector>
using namespace std;

/***
买附件,必须买主件
主件有0,1,2个附件。

每件的价格是10n,预算为N;每个物品的重要度[1, 5]
满意度: 价格与重要度的乘积的综合。
*/
int main() {
    int N, m;
    cin >> N >> m;

    vector<int> v(m + 1);
    vector<int> p(m + 1);
    vector<int> q(m + 1);
    vector<bool> flag(m + 1, false);    // 记录那些主件有附件
    for (int i = 1; i <= m; i++) {
        cin >> v[i] >> p[i] >> q[i];
        if (q[i] != 0) {
            flag[q[i]] = true;
        }
    }

    vector<int> f(N + 1, -0x7f7f7f7f);
    f[0] = 0;
    for (int i = 1; i <= m; i++) {
        // 附件不单独处理
        if (q[i] != 0) continue;
        
        // 对主件的子背包进行处理
        if (flag[i]) {
            int i_cnt = 0;
            int i_v = 0;
            vector<int> i_sub;
            for (int k = 1; k <= m; k++) {
                if (q[k] == i) {
                    i_sub.push_back(k);
                    i_cnt++;
                    i_v += v[k];
                }
            }

            i_v = min(N - v[i], i_v);
            vector<int> f_sub(i_v + 1, -0x7f7f7f);    // f_sub的个数是值域
            f_sub[0] = 0;

            for (int j = 0; j < i_cnt; j++) {
                for (int k = i_v; k >= v[i_sub[j]]; k--) {
                    f_sub[k] = max(f_sub[k], f_sub[k - v[i_sub[j]]] + v[i_sub[j]] * p[i_sub[j]]);
                    // if(f_sub[k] > 0){
                    //     printf("i_v:%d, j:%d, k:%d, f_sub[k-v[j]]:%d, add:%d, f[new]:%d\n",
                    //     i_v, i_sub[j], k, f_sub[k - v[i_sub[j]]], v[i_sub[j]] * p[i_sub[j]], f_sub[k]);
                    // }
                }
            }
            
		  	// 主件进行背包,并将主件的副件的子背包嵌入
            for (int j = N; j >= v[i]; j--) {
                // 处理主件
                f[j] = max(f[j], f[j - v[i]] + v[i] * p[i]);
                // if (f[j] > 0) {
                //     printf("i:%d, j:%d, f[j-v[i]]:%d, add:%d, f[j]:%d\n", i, j, f[j - v[i]], v[i] * p[i], f[j]);
                // }
                
                // 将子背包与父件合并,并同步至父背包
                for (int k = 0; k <= i_v; k++) {
                    if (f_sub[k] > 0 && j - v[i] - k >= 0) {
                        f[j] = max(f[j], f[j - v[i] - k] + f_sub[k] + v[i] * p[i]);
                        // if(f[j] > 0){
                        //     printf("merge, j:%d, k:%d, f[j-v[i]-k]:%d, add:%d, f[j]:%d\n", j, k, f[j - v[i] - k],
                        //     f_sub[k] + v[i] * p[i], f[j]);
                        // }
                    }
                }
            }            

        }
	  	// 对没有子件的背包进行处理
        else{
            for (int j = N; j >= v[i]; j--) {
                f[j] = max(f[j], f[j - v[i]] + v[i] * p[i]);
                // if (f[j] > 0) {
                //     printf("nosub_i:%d, j:%d, f[j-v[i]]:%d, add:%d, f[j]:%d\n", i, j, f[j - v[i]], v[i] * p[i], f[j]);
                // }
            }            
        }
    }
    int ans = 0;
    for (int i = 1; i <= N; i++) {
        if (f[i] > ans) ans = f[i];
    }
    cout << ans << endl;
    return 0;
}

// 64 位输出请用 printf("%lld")

全部评论

相关推荐

今天周一休息,突发奇想写一篇阶段总结。如题,我已经去了一个和Java彻底毫无关联的行业。曾经我以为自己能在计算机行业发光发热,没想到刚入行一年多就当了逃兵。从最开始的热爱到现在一看到代码就厌恶,不知道自己经历了什么。所以我去干什么了?答案是:在成都当了租房销售。上班那会压力大了就念叨着去干租房中介,但是一直下不去这个决心,想着自己学了四年多的计算机知识,终究还是不甘心。终于在某一天准备八股文的时候,看着无数篇和工作内容关系不大的理论知识,那一刻下定决心,决定尝试一下销售行业,也算是给自己一个交代。后面阴差阳错的投了成都自如去当租房管家,没想到面试很顺利,在当天一百多个面试的人里面,我成为了为数不多通过的几个幸运儿之一。目前已经培训通过,正式入职,也开了单,也有压力但是每天过得很开心,真心喜欢那种和人交流的感觉,哪怕是最后没有选择找我租房。说这些也是想告诉那些大三,大四正在找Java实习而焦虑的同学:你们现在还年轻,选择很多,容错率也很高,可以尽情去尝试自己喜欢的行业和工作。不用因为某一次的面试没通过或者简历石沉大海而焦虑,更不用因为身边人都在挤编程的独木桥就强迫自己跟风。也算是自己的碎碎念吧,也希望自己能在新的领域取得一点小成就。也祝牛油工作顺利!
沉淀小子:干啥都不丢人啊,生存是必须要的,销售很考验一个人综合素质能力的,好的销售人脉和资源可不比写字楼的白领差啊
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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