算法 | 用贪心求解背包动态规划、回溯、分支限界法求解0-1背包

背包问题

普通背包:

贪心时间复杂度:O(nlogn)

首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心 选择策略,将尽可能多的单位重量价值最高的物品装入背包。若 将这种物品全部装入背包后,背包内的物品总重量未超过C,则选 择单位重量价值次高的物品并尽可能多地装入背包。依此策略一 直地进行下去,直到背包装满为止

//program 2.3 背包问题 
#include<iostream>
#include<algorithm>
using namespace std;
const int M=10005;
struct node{double w;//每个物品的重量double v;//每个物品的价值double p;//性价比
}s[M];bool cmp(node a,node b){//自定义比较函数 return a.p>b.p;//根据物品的单位价值从大到小排序
}double solve(int n,double W){double sum=0.0;//sum表示示装入物品的价值之和double cleft=W;//背包剩余容量 for(int i=0;i<n;i++){//贪心算法求解 if(s[i].w<=cleft){//如果物品的重量小于等于剩余容量 cleft-=s[i].w;sum+=s[i].v;}else{//如果物品的重量大于剩余容量 sum+=cleft*s[i].p;//部分装入break;}}return sum; 
}int main(){int t,n;//t为测试用例个数,n为物品个数double W;//背包容量 cin>>t;while(t--){cin>>n>>W;for(int i=0;i<n;i++){cin>>s[i].w>>s[i].v;s[i].p=s[i].v/s[i].w;//每个宝物单位价值}sort(s,s+n,cmp);cout<<solve(n,W)<<endl;//输出装入宝物的最大价值}return 0;
}

分别用动态规划法、回溯法、分支限界法设计 0-1背包问题 

 动态规划法时间复杂度:O(nc) c是背包容量。

这是因为需要填写一个二维数组来记录子问题的解。

//program 4.8 01背包 
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=105;
const int maxw=10005;
int c[maxn][maxw];//c[i][j]表示前i个物品放入容量为j的背包获得的最大价值
int w[maxn],v[maxn];//w[i]表示第i个物品的重量,v[i]表示第i个物品的价值
bool x[maxn]; //x[i]表示第i个物品是否放入背包int knapsack(int n,int W){for(int i=1;i<=n;i++){//计算c[i][j]for(int j=1;j<=W;j++){if(j<w[i])  //当物品的重量大于背包的容量,则不放此物品c[i][j]=c[i-1][j];else    //否则比较此物品放与不放哪种情况使得背包内的价值最大c[i][j]=max(c[i-1][j],c[i-1][j-w[i]]+v[i]);} }return c[n][W];
}void print(int n,int W){//逆向构造最优解int j=W;for(int i=n;i>0;i--){if(c[i][j]>c[i-1][j]){x[i]=1;j-=w[i];}elsex[i]=0;}cout<<"装入背包的物品序号为:";for(int i=1;i<=n;i++){if(x[i])cout<<i<<"  ";}  cout<<endl; 
}int main(){int n,W,t;//n表示n个物品,W表示背包的容量,t表示测试用例数 cin>>t;while(t--){cin>>n>>W;for(int i=1;i<=n;i++)cin>>w[i]>>v[i];for(int i=1;i<=n;i++)//初始化第0列为0c[i][0]=0;for(int j=1;j<=W;j++)//初始化第0行为0c[0][j]=0;cout<<knapsack(n,W)<<endl;//print(n,W);}return 0;
}
/*测试数据 
2
5 10
2 6
5 3
4 5
2 4
3 6
4 52
12 13
10 24
22 13
9 24
*/

回溯法O(2的n次方)

//program 5.2 01背包 
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=105;
int n; //物品数量
double W; //背包容量
double w[maxn],v[maxn];//w[i]表示第i个物品的重量,v[i]表示第i个物品的价值
double cw,cp,bestp; //当前重量,当前价值,最优值
bool x[maxn];  //x[i]表示第i个物品是否放入背包
bool bestx[maxn];  //最优解double bound(int i){//计算上界(已装入物品价值+剩余物品(第i~n种物品)的总价值)double rp=0;while(i<=n){//依次计算剩余物品的价值rp+=v[i];i++;}return cp+rp;
}void backtrack(int t){//回溯法,t为层次 if(t>n){//到达叶子for(int j=1;j<=n;j++)//记录最优解 bestx[j]=x[j];bestp=cp;//记录最优值 return ;}if(cw+w[t]<=W){//如果满足约束条件,搜索左子树x[t]=1;cw+=w[t];cp+=v[t];backtrack(t+1);cw-=w[t];//还原现场 cp-=v[t];}if(bound(t+1)>bestp){//如果满足限界条件,搜索右子树x[t]=0;backtrack(t+1);}
}int knapsack(){cw=0.0,cp=0.0,bestp=0.0; //当前放入背包的物品重量,价值,最优值backtrack(1);cout<<bestp<<endl;
//    for(int i=1;i<=n;i++){ //输出最优解
//        if(bestx[i]==1)
//    		cout<<i<<" ";
//    }
//	cout<<endl;
}int main(){int t;//t表示测试用例数 cin>>t;while(t--){cin>>n>>W;for(int i=1;i<=n;i++)cin>>w[i]>>v[i];knapsack();}return 0;
}
/*测试数据 
2
5 10
2 6
5 3
4 5
2 4
3 6
4 52
12 13
10 24
22 13
9 24
*/

分支限界法时间复杂度接近于O(2^n)

//program 6.2 01背包 普通队列bfs AC 831ms 
#include<iostream>
#include<queue>
using namespace std;
const int maxn=105;
int n; //物品数量
double W; //背包容量
double w[maxn],v[maxn];//w[i]表示第i个物品的重量,v[i]表示第i个物品的价值
double bestp,sumv; //当前重量,当前价值,最优值,总价值  
bool bestx[maxn];  //最优解struct node{double cp,rp; //cp当前放入背包的物品价值,rp剩余物品的价值double rw; //剩余容量int id; //物品号node() {}node(double _cp,double _rp,double _rw,int _id){cp=_cp;rp=_rp;rw=_rw;id=_id;}
};void knapsack_bfs(){queue<node> q; //创建一个普通队列(先进先出)q.push(node(0,sumv,W,1)); //根结点入队 while(!q.empty()){ //如果队列不空node cur,lc,rc;//定义三个结点型变量cur=q.front();//取出队头元素q.pop(); //队头元素出队
//        cout<<cur.cp<<" "<<cur.rp<<" "<<cur.rw<<" "<<cur.id<<endl;int t=cur.id;//当前物品序号if(t>n) continue;if(cur.cp+cur.rp<bestp) continue;int cp=cur.cp;int rp=cur.rp-v[t];if(w[t]<=cur.rw){ //满足约束条件,可以放入lc=node(cp+v[t],rp,cur.rw-w[t],t+1);//生成左孩子 if(lc.cp>bestp)//比最优值大更新bestp=lc.cp;q.push(lc);//左孩子入队}if(cp+rp>bestp){//满足限界条件rc=node(cp,rp,cur.rw,t+1);//生成右孩子 q.push(rc);//右孩子入队}}
}int main(){int t;//t表示测试用例数 cin>>t;while(t--){cin>>n>>W;bestp=0.0,sumv=0.0; //sumv为所有物品的总价值for(int i=1;i<=n;i++){cin>>w[i]>>v[i];sumv+=v[i];} knapsack_bfs();cout<<bestp<<endl;}return 0;
}
/*测试数据 
1
4 10
2 6
5 3
4 5
2 4
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/25285.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IO流字符流(FileReader与FileWriter)

目录 FileReader 空参read方法 带参read方法&#x1f447; FileWriter void write(intc) 写出一个字符 void write(string str) 写出一个字符串 void write(string str,int off,int len) 写出一个字符串的一部分 void write(char[] cbuf) …

Web前端伯乐在线:探索技术的深度与广度

Web前端伯乐在线&#xff1a;探索技术的深度与广度 在浩瀚的互联网海洋中&#xff0c;Web前端技术犹如一艘航行在波涛汹涌的海洋中的巨轮&#xff0c;承载着无数的创新与可能。而在这个领域里&#xff0c;伯乐在线就像一座灯塔&#xff0c;照亮着前行者的道路&#xff0c;引领…

备战 清华大学 上机编程考试-冲刺前50%,倒数第5天

T1&#xff1a;多项式求和 小K最近刚刚习得了一种非常酷炫的多项式求和技巧&#xff0c;可以对某几类特殊的多项式进行运算。非常不幸的是&#xff0c;小K发现老师在布置作业时抄错了数据&#xff0c;导致一道题并不能用刚学的方法来解&#xff0c;于是希望你能帮忙写一个程序…

C语言 树与二叉树基础部分

树与二叉树基础部分 树的基础概念二叉树的性质二叉树的遍历前序遍历中序遍历后序遍历层序遍历根据遍历结果恢复二叉树 二叉树的创建第一种第二种 二叉树的其他典型操作查找指定元素&#xff08;一般二叉树&#xff09;二叉树的高度&#xff08;深度&#xff09;二叉树的拷贝二叉…

!力扣102. 二叉树的层序遍历

给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]] /*** Definition for…

大模型应用工程化过程

近年来&#xff0c;以人工智能为代表的新一代信息技术加速应用&#xff0c;特 别是基于大模型、大数据、大算力的 ChatGPT 的发布&#xff0c;标志着人 工智能技术取得里程碑式突破&#xff0c;推动科技创新进入新阶段。随着 大模型技术的迅猛发展和场景价值的不断涌现&#xf…

9.2 Go 接口的实现

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

Day44 代码随想录打卡|二叉树篇---找树左下角的值

题目&#xff08;leecode T513&#xff09;&#xff1a; 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 方法&#xff1a;本题需要找二叉树左下角的值&#xff0c;因此该节点首先是在最后一行&#xff0…

搭建智慧互联网医院系统教学:源码解析与在线问诊APP开发

本篇文章&#xff0c;小编将以“源码解析与在线问诊APP开发”为切入点&#xff0c;详细介绍搭建智慧互联网医院系统的过程。 一、智慧互联网医院系统的架构设计 系统架构概述 -前端 -后端 -数据库 功能模块划分 -用户 -预约 -挂号 -问诊、 -病历 -管理 -药品 -配送…

Web前端发展路线:深度解析与未来展望

Web前端发展路线&#xff1a;深度解析与未来展望 在数字化时代的浪潮中&#xff0c;Web前端技术日新月异&#xff0c;成为推动互联网行业发展的重要引擎。本文将从四个方面、五个方面、六个方面和七个方面&#xff0c;深入探讨Web前端的发展路线&#xff0c;为您揭示这一领域的…

C++ 分治法找到第K大的数

有一个整数数组&#xff0c;请你根据快速排序的思路&#xff0c;找出数组中第 k 大的数。 例如&#xff1a; 输入 [1,3,5,2,2], 找出数组中第2大的数&#xff0c;输出 3. #include <iostream>using namespace std; #include <stack> #include <string> #i…

Pytorch 从零实现 Transformer

前言 之前虽然了解过 Transformer 架构&#xff0c;但是没有自己实现过。 最近阅读 transformers 库中 Llama 模型结构&#xff0c;于是想试着亲手实现一个简单的 Transformer。 在实现过程中加深了理解&#xff0c;同时发现之前阅读 Llama 中一些错误的地方&#xff0c;因此…

【实战项目二】Python爬取豆瓣影评

目录 一、环境准备 二、编写代码 一、环境准备 pip install beautifulsoup4 pip intall lxml pip install requests我们需要爬取这些影评 二、编写代码 我们发现每个影评所在的div的class都相同&#xff0c;我们可以从这入手 from bs4 import BeautifulSoup import request…

Java数据结构与算法(爬楼梯动态规划)

前言 爬楼梯就是一个斐波那契数列问题&#xff0c;采用动态规划是最合适不过的。 实现原理 初始化:dp[0]1;dp[1]2; 转移方程&#xff1a;dp[i]dp[i-1]d[i-2]; 边界条件:无 具体代码实现 class Solution {public int climbStairs(int n) {if(n1){return 1;}int[] dpnew i…

Qwen2大模型微调入门实战(完整代码)

Qwen2是通义千问团队的开源大语言模型&#xff0c;由阿里云通义实验室研发。以Qwen2作为基座大模型&#xff0c;通过指令微调的方式实现高准确率的文本分类&#xff0c;是学习大语言模型微调的入门任务。 指令微调是一种通过在由&#xff08;指令&#xff0c;输出&#xff09;对…

倩女幽魂手游攻略:云手机自动搬砖辅助教程!

《倩女幽魂》手游自问世以来一直备受玩家喜爱&#xff0c;其精美画面和丰富的游戏内容让人沉迷其中。而如今&#xff0c;借助VMOS云手机&#xff0c;玩家可以更轻松地进行搬砖&#xff0c;提升游戏体验。 一、准备工作 下载VMOS云手机&#xff1a; 在PC端或移动端下载并安装VM…

VS2015中配色方案

为Visual Studio 2017设置C#/C代码配色方案——Monokai风格 windows客户端开发–改变visual studio配色方案

多线程打印

1、固定运行顺序 比如&#xff0c;必须先 2 后 1 打印 1.1、wait notify 版 public class Test1 {// 先打印2&#xff0c;后打印1static final Object lock new Object();static boolean t2runned false; //表示t2是否运行过public static void main(String[] args) {Thr…

流程的控制

条件选择语句 我们一般将条件选择语句分为三类&#xff1a; 单条件双条件多条件 本篇文章将分开诉说着三类。 单条件 单条件的语法很简单&#xff1a; if (条件) {// 代码}条件这里我们需要注意下&#xff0c;可以向里写入两种&#xff1a; 布尔值布尔表达式 当然&…

Docker高级篇之Docker网络

文章目录 1. Docker Network简介2. Docker 网络模式3. Docker 网络模式之bridge4. Docker 网络模式之host5. Docker 网络模式之none6. Docker 网络模式之container7. Docker 网络模式之自定义网络模式 1. Docker Network简介 从Docker的架构和运作流程来看&#xff0c;Docker是…