【实验目的】
1、熟练掌握动态规划思想及教材中相关经典算法。
2、使用动态规划法编程,求解0/1背包问题和TSP问题。

TSP问题

一、实验内容:
TSP问题是指旅行家要旅行n个城市,要求每个城市经历且仅经历一次然后回到出发城市,并要求所走的路程最短。
对于图G=(V,E),假设从顶点i出发,令V’=V-i,则d(i,V’)表示从顶点i出发经过V’中各个顶点一-次且仅一次,最后回到出发点i的最短路径长度,显然,初始子问题是d(k,{}),即从顶点i出发只经过顶点k回到顶点i。现在考虑原问题的一部分,d(k,V’-{k})表示从顶点k出发经过V’-{k}中各个顶点一次且仅一次,最后回到出发点i的最短路径长度,则:
d(k, {}) = c[k][i]
d(i, V’) = min{c[i][k]+d(k,V’- {k})}(k∈V’)
如图为最近邻点贪心策略求解TSP问题的过程。


假设n个顶点分别用0n-1的数字编号,顶点之间的代价存放在数组arcrnT[n]中,下面考虑从顶点0出发求解TSP问题的填表形式。首先,按个数为1、2、…n1的顺序生成1n-1个元素的子集存放在数组V[2^(n-1)]中。
例如当n=4时,V[1]={1},V[2]={2},V[3]={3},V[4]={1,2},V[5]={1,3},V[6]={2,3},V[7]={1,2,3}。设数组d[n][2^(n-1)]存放迭代结果,其中d[i][j]表示从顶点i经过子集V[j]中的顶点一次且仅一次,最后回到出发点0的最短路径长度,动态规划法求解TSP问题的算法如下。

三、实验源程序及结果截图:
1、实验代码:

#include<iostream>
#include<iomanip>
using namespace std;
int main()
{int n,i,j,k,m=1;cout<<"请输入顶点个数:\n";cin>>n;for(i=1;i<n;i++){//n个顶点有m个子集,m=2^(n-1)m=m*2;} int **arc=new int*[n];//图的代价矩阵for(i=0;i<n;i++){ arc[i]=new int[n];} int **d=new int*[n];//存放迭代结果,即过程矩阵for(i=0;i<n;i++){ d[i]=new int[m];} cout<<"请输入带权图的代价矩阵:"<<endl;for(i=0;i<n;i++){for(j=0;j<n;j++){cin>>arc[i][j];}         }       //纠正用户输入的数据for(i=0;i<n;i++)arc[i][i]=-1;//初始化第0列for(i=0;i<n;i++){d[i][0]=arc[i][0];}      //填过程矩阵for(j=1;j<m;j++){for(i=1;i<n;i++){d[i][j] = 0x7ffff;//设0x7ffff为无穷大if(((j>>(i-1))&1)==1) //对于数字x,要看它的第i位是不是1,通过判断布尔表达式 (((x >> (i - 1) ) & 1) == 1的真值来实现continue;                  //若第i位是1,就说明子集j里包含i这个元素,d[i][j]这个空就无需计算for(k=1;k<n;k++){/*找出集合j中有哪些元素,比如,(6>>(2-1))&1==1,说明集合{2.3}中有元素2*/if(((j>>(k-1))&1)==0)    //集合中没有此元素就跳过continue;if(d[i][j]>arc[i][k]+d[k][j^(1<<(k-1))])d[i][j]=arc[i][k]+d[k][j^(1<<(k-1))];}}}//计算d[0][m-1]for(j=0;j<m-1;j++)d[0][j]=-1;d[0][m-1] = 0x7ffff;for (k=1;k<n;k++){      if(((m-1>>(k-1))&1)==0) continue;if (d[0][m-1]>arc[0][k]+d[k][(m-1)^(1<<(k-1))])d[0][m-1]=arc[0][k]+d[k][(m-1)^(1<<(k-1))];}cout<<"最短路径为:"<<d[0][m-1]<<endl;cout<<"过程矩阵为:"<<endl;cout<<'\t';for(j=0;j<m;j++)cout<<j<<'\t';cout<<endl;for(i=0;i<n;i++){cout<<i<< '\t';for(j=0;j<m;j++){if(d[i][j]==0x7ffff)d[i][j]=-1;cout<<d[i][j]<<'\t';}cout<<endl;}getchar();getchar();return 0;
}

2、运行结果:

四、实验的分析与思考:
在十进制数的二进制表示中,哪位为1则集合中就有哪个数。十进制6的二进制110中,第二三位是1,则6代表集合{2,3},因此,定下一条规则,过程矩阵d[i][j]中,若j=0,代表集合{ };j=1,代表集合{1}……j=5,代表集合{1,3}……以此类推。
判断一个顶点是否位于子集中时,例如要判断集合j={1,3,5,6,7}是否有顶点3。集合j={1,3,5,6,7}表示成二进制串为1110101,其中集合里面有的数对应的位数写成1,没有的写成0。要在集合中找顶点3,就是要判断二进制串第3位是不是1,就把1110101右移(3-1)位,得到11101,然后结果和00001进行&运算,如果结果是1说明第3位是1,则说明顶点在子集中。故判断公式为(j>>(i-1))&1==1。
填写过程矩阵过程时,以d[2][5]为例,d[2][5]=d(2,{1,3})。d[2][5] 表示从2出发,通过{1,3},最后回到起点。那么d[2][5] = min{arc[2][1] + d(1,{3}),arc[2][3] + d(3,{1})} = min{arc[2][1] + d[1][4],arc[2][3] + d[3][1]}。从2出发,要去{1,3},先考虑去1的路。去了1后集合{1,3}中只剩下{3} ,{3}对应二进制100,十进制4,所以要求的d表就是d[1][4],这个4可以通过(101)^(1)得到,而(1) = 1<<(1-1).其中,二进制101(十进制5)代表集合{1,3};再看去3的路,去了3后集合{1,3}中只剩下{1},{1}对应二进制001,十进制1,所以要求的d表就是d[3][1],1通过(101) ^ (100)得到,而(100) = 1<<(3-1)。故此处又总结出一个公式d[i][j] = min{arc[i][k] + d[k][j ^ (1 << (k - 1))]}。

0-1 背包问题

一、实验内容:
0/背包问题可以看做是决策一个序列(x1,x2…xn),对任一变量x的决策是决定xi=1还是xi=0.设V(n.C)表示将n个物品装人容量为C的背包获得的最大价值,显然初始子问题是把前面i个物品装人容量为0的背包和把0个物品装人容量为j的背包,得到的价值均为0,即:
V(i,0)=V(0,j)=0 0≤i≤n,0≤j≤C
考虑原问题的一部分,设V(i,j)表示将前i(1≤i≤n)个物品装人容量为j(1≤j≤C)的背包获得的最大价值,在决策xi时,已确定了(x1,…,xi-1),则问题处于下列两种状态之一:
(1)背包容量不足以装人物品i,则装入前i个物品得到的最大价值和装人前i-1个物品得到的最大价值是相同的,即xi=0,背包不增加价值。
(2)背包容量可以装入物品i,如果把第i个物品装入背包,则背包中物品的价值等于把前i-1个物品装人容量为j-wi的背包中的价值加上第i个物品的价值vi,如果第i个物品没有装人背包,则背包中物品的价值等于把前i-1个物品装人容量为j的背包中所取得的价值。显然,取二者中价值较大者作为把前i个物品装人容量为j的背包中的最优解。则得到如下递推式:
V(i,j)=V(i-1,j) j<wi
V(i,j)=max{V(i-1,j),V(i-1,j-wi)+v} j≥wi
为了确定装人背包的具体物品,从V(n,C)的值向前推,如果V(n,C)>V(n-1,C),表明第n个物品被装人背包,前n-1个物品被装人容量为C-wn的背包中;否则,第n个物品没有被装人背包,前n-1个物品被装人容量为C的背包中。依此类推,直到确定第1个物品是否被装入背包中为止。由此,得到如下函数:
xi=0 V(i,j)=V(i-1,j)
xi=1 j=j-wi V(i,j)>V(i-1,j)

二、实验源程序及结果截图:
1、实验代码:

#include <iostream>
using namespace std;int KnapSack(int C, int n, int w[], int v[])
{int V[n+1][C+1];for(int i = 0; i <= n; i++){V[i][0] = 0;//第0列置零 }for(int j = 0; j <= C; j++){V[0][j] = 0;//第0行置零 }//计算第i行,进行第i次迭代for(int i = 1; i <= n; i++){for(int j = 1; j <= C; j++){if(j < w[i])V[i][j] = V[i-1][j];elseV[i][j] = max(V[i-1][j], V[i-1][j-w[i]]+v[i]);}}//装入的物品int x[n];int j = C;cout<<"装入的物品为:";for(int i = n ; i > 0; i--){if(V[i][j] > V[i-1][j]){x[i] = 1;j = j - w[i];}elsex[i] = 0;//cout<<x[i]<<'\t';}for(int i=1;i<=n;i++){if(x[i]==1)printf("物品%d    ",i);}cout<<endl;return V[n][C];
}
int main()
{int n;int C;cout<<"请输入物品的个数:";cin>>n;cout<<"请输入背包的容量:";cin>>C;int v[n];int w[n];cout << "请输入物品的重量:";for(int i = 1 ; i <= 5 ; i++ ){cin >> w[i];}cout << "请输入物品的价值:";for(int  i = 1; i <= 5; i++){cin >> v[i];}cout << "最大价值为:" << KnapSack(C,n,w,v);
}

2、运行结果:

三、实验的分析与思考:
首先输入物品个数n、背包容量C、物品重量w[]和价值v[]。将二维表V[n+1][C+1]的第0行和第0列元素置零,然后填表(如果背包容量小于物品重量则不装入,否则比较V[i-1][j]和V[i-1][j-w[i]]+v[i],取二者中价值较大者作为把前i个物品装人容量为j的背包中的最优解),最后输出装入的物品结果。

算法设计与分析实验二:动态规划法实现TSP问题和0/1背包问题相关推荐

  1. 深大算法设计与分析实验二——分治法求最近点对问题

    源代码: 深大算法设计与分析实验二--分治法求最近点对问题代码-C/C++文档类资源-CSDN下载 目录 实验问题 一.实验目的: 二.内容: 三.算法思想提示 产生不重复的随机点算法: 蛮力算法: ...

  2. 算法设计与分析 实验二 分治法求解最近点对问题

    分治法求解最近点对问题 一.实验目的与要求 1.实验基本要求 2.实验亮点 二.实验内容与方法 三.实验步骤与过程 (一)一些准备工作 1.实验流程 2.数据生成与去除重复点 (二)暴力穷举法 1.算 ...

  3. 算法设计与分析 实验二 贪心算法

    实验2.<贪心算法实验> 一.实验目的 了解贪心算法思想 掌握贪心法典型问题,如背包问题.作业调度问题等. 二.实验内容 编写一个简单的程序,实现单源最短路径问题. 编写一段程序,实现找零 ...

  4. 计算机算法设计与分析 动态规划 实验报告,动态规划法解最长公共子序列(计算机算法设计与分析实验报告).doc...

    动态规划法解最长公共子序列(计算机算法设计与分析实验报告) 实报 告 实验名称:任课教师::姓 名:完成日期:二.主要实验内容及要求: 要求按动态规划法原理求解问题: 要求交互输入两个序列数据: 要求 ...

  5. 太原理工大学linux与python编程r实验报告_太原理工大学算法设计与分析实验报告...

    <太原理工大学算法设计与分析实验报告>由会员分享,可在线阅读,更多相关<太原理工大学算法设计与分析实验报告(12页珍藏版)>请在人人文库网上搜索. 1.本科实验报告课程名称: ...

  6. C/C++ 算法设计与分析实验报告

    算法设计与分析实验报告 算法实验整体框架的构建 菜单代码块 选择函数代码块 主函数代码块 实验模块Ⅰ:算法分析基础--Fibonacci序列问题 实验解析 Fibonacci序列问题代码块 实验模块Ⅱ ...

  7. 格雷码算法c语言实验报告,算法设计与分析实验报告

    本科生实验报告 课程名称:算法设计与分析 实验项目:递归和分治算法 实验地点:计算机系实验楼110 专业课:物联网1601学生.2016002105 学生姓名:于 指导员:郝晓丽 2018年5月4日 ...

  8. 算法设计与分析实验指导(完整版)

    算法设计与分析实验指导 文章目录 算法设计与分析实验指导 1. 快速排序及第k小数 1.1 快速排序 1.1.1 Implementation 1 1.1.2 算法特性分析 1.1.3 Improve ...

  9. 【图的着色问题】算法设计与分析实验1

    计算机科学与工程学院实验报告 课程名称 算法设计与分析 班级 实验内容 实验1:图的着色问题 指导教师 姓名 重剑DS 学号 实验日期 2022.04.28 一.问题描述,含输入.输出数据内容.格式 ...

最新文章

  1. VMware虚拟机NAT模式的具体配置
  2. 跑yolo3模型出的效果图_效果图和效果图设计到底有什么区别?区别大着呢,亲……...
  3. 在原有Android项目中快速集成React Native
  4. 荒径 弗罗斯特_弗罗斯特庞克,颠覆性城市建设者
  5. 科研分享|一个论文关系网络可视化网站
  6. 12种Javascript解决常见浏览器兼容问题的方法
  7. java判断字符串中是否含有某个字符串
  8. mysql start
  9. Windows Mobile 系列文章索引---不断整理中(2009-07-08)
  10. idea导入java项目步骤,idea与eclipse项目相互导入的过程(图文教程)
  11. [学习windows/记录篇]使用tmg三向外围发布ssl安全的web网站
  12. java mvc controller_java之spring mvc之Controller配置的几种方式
  13. Java游戏聊斋聂小倩_【聊斋故事汇】之聂小倩(篇一)
  14. 【ceph】ceph分布式存储MDS(各种状态、源码)
  15. 机器学习的三大主要任务
  16. Thinkphp3.2如何where查询条件如何同时添加字符串条件和数组条件
  17. arcgis导入坐标点转面_点数据转成Arcgis线、面文件
  18. GPS之MTK平台代码小结以及gps协议注释
  19. android直播切换浮窗,直播悬浮窗怎么设置
  20. 快递员能开你家锁了,问你怕不怕?

热门文章

  1. sublime工具的使用
  2. 记录一次自己刷bios
  3. android 横向竖排文字,Android TextView 横排文字变竖排的简单方法
  4. C/C++ 通过域名获取服务器真实IP地址
  5. OpenGL自制游戏引擎-GreateWindow
  6. 机械优化黄金分割法c语言编程,黄金分割法_机械优化设计_C语言程序.doc
  7. 软件工程----生命周期模型
  8. C++实现_数据分类处理(牛客网华为机试题)
  9. 在线考试系统网站 毕业设计毕设源码毕业论文开题报告参考(1)功能概要
  10. 华为认证考试费用是多少?