当前位置: 首页 > news >正文

牛客:HJ16 购物单【01背包】【华为机考】

学习要点

  1. 深入理解回溯
  2. 深入理解01背包问题

题目链接

        购物单_牛客题霸_牛客网

题目描述

解法1:回溯

        其实此题非常符合取子集的逻辑,但是时间复杂度太高。通过11/14。想写出来这个回溯过程,不容易。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int money; // 有多少钱
int max_value = 0; // 礼物最终的最大价值
bool check[66];void dfs(vector<vector<int>>& v_big, int pos, int path_value, int path_cost) {for (int i = pos; i <= v_big.size() - 1; i++) {// 主件不附带他人,但是有可能已经被别的附带// 没有被添加过的主件if (v_big[i][3] == 0 && check[i] == false) {// 还可以买这个主件if ((path_cost + v_big[i][1]) <= money) {check[i] = true;max_value = max(max_value, path_value + v_big[i][1] * v_big[i][2]);if ( i == v_big.size()) {check[i] = false;break;}dfs(v_big, i + 1, path_value + v_big[i][1] * v_big[i][2],path_cost + v_big[i][1]);check[i] = false;}// 钱不够了,不能买这个主件else {max_value = max(max_value, path_value);// if (i != v_big.size() - 1) {//     continue;// }}}// 已经被添加过的主件else if (v_big[i][3] == 0 && check[i] == true) {// if (i != v_big.size() - 1) {//     continue;// }}// 附件附带的主件有可能被添加过,有可能没有被添加过// 已经添加主件的附件else if (v_big[i][3] != 0 && check[v_big[i][3]] == true) {// 还可以买这个附件if ((path_cost + v_big[i][1]) <= money) {check[i] = true;max_value = max(max_value, path_value + v_big[i][1] * v_big[i][2]);if ( i == v_big.size()) {check[i] = false;break;}dfs(v_big, i + 1, path_value + v_big[i][1] * v_big[i][2],path_cost + v_big[i][1]);check[i] = false;}// 钱不够了,不能买这个附件else {max_value = max(max_value, path_value);// if (i != v_big.size() - 1) {//     continue;// }}}// 没有添加主件的附件else if (v_big[i][3] != 0 && check[v_big[i][3]] == false) {// 还可以买这个附件if ((path_cost + v_big[i][1] + v_big[v_big[i][3]][1] ) <= money) {check[i] = true;check[v_big[i][3]] = true;max_value = max(max_value, path_value + v_big[i][1] * v_big[i][2]);if ( i == v_big.size()) {check[i] = false;break;}dfs(v_big, i + 1, path_value + v_big[i][1] * v_big[i][2] +v_big[v_big[i][3]][1] * v_big[v_big[i][3]][2],path_cost + v_big[i][1] + v_big[v_big[i][3]][1]);check[i] = false;check[v_big[i][3]] = false;}// 钱不够了,不能买这个附件{max_value = max(max_value, path_value);// if (i != v_big.size() - 1) {//     continue;// }}}else {}}
}int main() {int count;cin >> money >> count;// cout << money << " " << count << endl;vector<vector<int>> v_big(count + 1, vector<int>(4));int i = 1;while (i <= count) {cin >> v_big[i][1] >> v_big[i][2] >> v_big[i][3];i++;}// for(int j = 1; j<= count; j++)// {//     cout << v_big[j][1] << " "<< v_big[j][2] << " " << v_big[j][3] << endl;// }dfs(v_big, 1, 0, 0);cout << max_value << endl;return 0;
}

解法2:01背包

#include <bits/stdc++.h>
using namespace std;int main() {int count;int money;cin >> money >> count;// cout << money << " " << count << endl;vector<vector<int>> v_big(count + 1, vector<int>(4));int i = 1;while (i <= count) {cin >> v_big[i][1] >> v_big[i][2] >> v_big[i][3];i++;}// 简单改造一下这个数组for(int i = 1; i<=count;i++){v_big[i][1] = v_big[i][1] / 10;v_big[i][2] = v_big[i][2] * 10;if(v_big[i][3] != 0 ){int index = v_big[i][3];v_big[index].push_back(v_big[i][1]); v_big[index].push_back(v_big[i][2]);v_big[i][1] = 0; v_big[i][2] = 0; v_big[i][3] = 0;}}// 动归逻辑int num = money / 10;vector<vector<int>> dp(count + 1,vector<int>(num+1,0));// 首元素情况:无附件主件、单附件主件、双附件主件// 恰巧我们v_big[0]是全0,我们索性将其虚拟成0号物品这样方便我们进行初始化// 则全部初始化为0即可for(int i = 1; i<=count;i++){for(int j = 1; j<=num; j++){if(v_big[i][1] > j){dp[i][j] = dp[i-1][j];}else{// 不取该主件   int a = dp[i-1][j];// 只取该主件int b = dp[i-1][j - v_big[i][1]] + v_big[i][1] * v_big[i][2];// 取主件取单附件int c1 = 0;int c2 = 0;int c = 0;if(v_big[i].size() > 4){if((v_big[i][1] + v_big[i][4]) <= j){c1 = dp[i-1][j-v_big[i][1] - v_big[i][4]] + v_big[i][1] * v_big[i][2] + v_big[i][4] * v_big[i][5];}if((v_big[i][1] + v_big[i][6]) <= j){c2 = dp[i-1][j-v_big[i][1] - v_big[i][6]] + v_big[i][1] * v_big[i][2] + v_big[i][6] * v_big[i][7];}c = max(c1,c2);}// 取主件取双附件int d = 0;if(v_big[i].size() > 6){if((v_big[i][1] + v_big[i][4] + v_big[i][6]) <= j){d = dp[i-1][j-v_big[i][1] - v_big[i][4]- v_big[i][6]] + v_big[i][1] * v_big[i][2] + v_big[i][4] * v_big[i][5] + v_big[i][6] * v_big[i][7];}}int max1 = max(a,b); int max2 = max(c,d); int max3 = max(max1,max2);dp[i][j] = max3;}}}cout << dp[count][num]  << endl;return 0;}

http://www.lryc.cn/news/579508.html

相关文章:

  • 封装 获取paramsByKey 方法
  • 毕业设计(启智模块化机器人的组装与K5的使用
  • 使用Visual Studio 2022创建CUDA编程项目
  • 车载交换机动态MAC学习和静态MAC绑定如何获取MAC地址表
  • jenkins角色权限
  • 这才叫窗口查询!TDEngine官方文档没讲透的实战玩法
  • 微信小程序41~50
  • 佰力博科技与您探讨压电材料的原理与压电效应的应用
  • C++(std::sort)
  • 【轨物洞见】光伏机器人与组件、支架智能化协同白皮书
  • 如何避免服务器出现故障情况?
  • SPLADE 在稀疏向量搜索中的原理与应用详解
  • 【NLP入门系列四】评论文本分类入门案例
  • ubuntu 6.8.0 安装xenomai3.3
  • lspci查看PCI设备详细信息
  • OpenCV篇——项目(二)OCR文档扫描
  • Rust方法语法:赋予结构体行为的力量
  • ConcurrentHashMap 原理
  • Linux多线程(十二)之【生产者消费者模型】
  • 汽车ECU产线烧录和检测软件怎么做?
  • Flutter 3.29+使用isar构建失败
  • HarmonyOS ArkTS卡片堆叠滑动组件实战与原理详解(含源码)
  • Java网络编程:TCP/UDP套接字通信详解
  • I/O 进程 7.2
  • 在Ubuntu 24.04主机上创建Ubuntu 14.04编译环境的完整指南
  • (一)复习(模块注入/minimal api/EF和Dapper实现CQRS)
  • Ubuntu Gnome 安装和卸载 WhiteSur-gtk-theme 类 Mac 主题的正确方法
  • Frida:配置自动补全 in VSCode
  • TCP 三次握手与四次挥手详解
  • MyBatis 之基础概念与框架原理详解