背包问题和棋盘覆盖课程设计报告
背包问题实验报告
背包问题实验报告背包问题实验报告背包问题是计算机科学中的经典问题之一,它涉及到在给定的一组物品中选择一些物品放入背包中,以使得背包的总重量不超过其容量,并且所选择的物品具有最大的总价值。
在本次实验中,我们将通过不同的算法来解决背包问题,并对比它们的效率和准确性。
1. 实验背景和目的背包问题是一个重要的优化问题,它在许多实际应用中都有广泛的应用,比如货物装载、资源分配等。
在本次实验中,我们的目的是通过实际的算法实现,比较不同算法在解决背包问题时的性能差异,并分析其优缺点。
2. 实验方法和步骤为了解决背包问题,我们选择了以下几种常见的算法:贪心算法、动态规划算法和遗传算法。
下面将对每种算法的具体步骤进行介绍。
2.1 贪心算法贪心算法是一种简单而直观的算法,它通过每次选择当前状态下最优的解决方案来逐步构建最终解决方案。
在背包问题中,贪心算法可以按照物品的单位价值进行排序,然后依次选择单位价值最高的物品放入背包中,直到背包的容量达到上限。
2.2 动态规划算法动态规划算法是一种基于递推关系的算法,它通过将原问题分解为多个子问题,并利用子问题的解来构建原问题的解。
在背包问题中,动态规划算法可以通过构建一个二维数组来记录每个子问题的最优解,然后逐步推导出整个问题的最优解。
2.3 遗传算法遗传算法是一种模拟生物进化的算法,它通过模拟自然选择、交叉和变异等过程来搜索问题的最优解。
在背包问题中,遗传算法可以通过表示每个解决方案的染色体,然后通过选择、交叉和变异等操作来不断优化解决方案,直到找到最优解。
3. 实验结果和分析我们使用不同算法对一组测试数据进行求解,并对比它们的结果和运行时间进行分析。
下面是我们的实验结果:对于一个容量为10的背包和以下物品:物品1:重量2,价值6物品2:重量2,价值10物品3:重量3,价值12物品4:重量4,价值14物品5:重量5,价值20贪心算法的结果是选择物品4和物品5,总重量为9,总价值为34。
【优质】背包问题实验报告-范文word版 (13页)
本文部分内容来自网络整理,本司不为其真实性负责,如有异议或侵权请及时联系,本司将立即删除!== 本文为word格式,下载后可方便编辑和修改! ==背包问题实验报告篇一:背包问题实验报告课程名称:任课教师:班级:201X姓名:实验报告算法设计与分析实验名称:解0-1背包问题王锦彪专业:计算机应用技术学号:11201X 严焱心完成日期: 201X年11月一、实验目的:掌握动态规划、贪心算法、回溯法、分支限界法的原理,并能够按其原理编程实现解决0-1背包问题,以加深对上述方法的理解。
二、实验内容及要求:1.要求分别用动态规划、贪心算法、回溯法和分支限界法求解0-1背包问题;2.要求显示结果。
三、实验环境和工具:操作系统:Windows7 开发工具:Eclipse3.7.1 jdk6 开发语言:Java四、实验问题描述:0/1背包问题:现有n种物品,对1<=i<=n,第i种物品的重量为正整数Wi,价值为正整数Vi,背包能承受的最大载重量为正整数C,现要求找出这n种物品的一个子集,使得子集中物品的总重量不超过C且总价值尽量大。
动态规划算法描述:根据问题描述,可以将其转化为如下的约束条件和目标函数:nmax?vixi?n??wixi?C?i?1?x?{0,1}(1?i?n)?i寻找一个满足约束条件,并使目标函数式达到最大的解向量nX?(x1,x2,x3,......,xn)wixi,使得?i?1?C,而且?vixii?1n达到最大。
0-1背包问题具有最优子结构性质。
假设(x1,x2,x3,......,xn)是所给的问题的一个最优解,则(x2,x3,......,xn)是下面问题的一个最优解:?n??wixi?C?w1x1max?i?2?x?{0,1}(2?i?n)?i如果不是的话,设(y?vixi。
i?2nn2,y3,......,yn)是这个问题的一个最优解,则?viyi??vixi,且w1x1 i?2i?2n??wiyii?2?C。
背包问题实验报告
背包问题实验报告1. 引言背包问题是一类经典的组合优化问题,在现实生活中有着广泛的应用。
背包问题可以描述为:有一个背包容量为W的背包和N个物品,每个物品有一定的重量和价值,要求将物品放入背包中使得背包的总价值最大。
本实验旨在通过比较不同的算法策略,找到解决背包问题的最佳方法,以提高背包问题的求解效率。
2. 实验环境•操作系统:Windows 10•编程语言:Python 3.8•开发环境:Visual Studio Code3. 实验过程3.1 暴力穷举法暴力穷举法是解决背包问题的一种基本策略。
该方法通过遍历所有可能的组合,计算每个组合的价值,并找到最大价值的组合作为最优解。
具体步骤如下:1.初始化最大价值max_value为0,最优解combo为空集。
2.遍历所有可能的物品组合:–将组合中的物品放入背包中,计算背包中物品的总价值。
–若背包总价值超过max_value,则更新max_value和combo。
3.输出最优解combo和最大价值max_value。
该方法的时间复杂度为O(2^N),其中N为物品的数量,在物品数量较大时效率较低。
3.2 动态规划法动态规划法是解决背包问题的一种高效策略。
该方法通过构建价值表,利用子问题的最优解来求解背包问题的最优解。
具体步骤如下:1.初始化一个二维数组value_table,其中value_table[i][j]表示前i个物品放入容量为j的背包中的最大价值。
2.根据以下递推关系来填充value_table的值:–若第i个物品的重量大于背包容量j,则value_table[i][j]等于value_table[i-1][j],表示第i个物品不能放入背包中。
–若第i个物品的重量小于等于背包容量j,则value_table[i][j]等于max(value_table[i-1][j], value_table[i-1][j-w[i]]+v[i]),表示第i个物品可以选取并放入背包中,或不选取第i个物品。
实验报告:动态规划01背包问题)范文(最终五篇)
实验报告:动态规划01背包问题)范文(最终五篇)第一篇:实验报告:动态规划01背包问题)范文XXXX大学计算机学院实验报告计算机学院2017级软件工程专业班指导教师学号姓名2019年 10月 21日成绩课程名称算法分析与设计实验名称动态规划---0-1 背包问题①理解递归算法的概念实验目的②通过模仿0-1 背包问题,了解算法的思想③练习0-1 背包问题算法实验仪器电脑、jdk、eclipse 和器材实验:0-1 背包算法:给定N 种物品,每种物品都有对应的重量weight 和价值 value,一个容量为maxWeight 的背包,问:应该如何选择装入背包的物品,使得装入背包的物品的总价值最大。
(面对每个物品,我们只有拿或者不拿两种选择,不能选择装入物品的某一部分,也实验不能把同一个物品装入多次)代码如下所示:内 public classKnapsackProblem {容 /**、上 * @paramweight 物品重量机 * @paramvalue 物品价值调 * @parammaxweight背包最大重量试程 *@return maxvalue[i][j] 中,i 表示的是前 i 个物品数量,j 表示的是重量序 */、publicstaticint knapsack(int[]weight , int[]value , intmaxweight){程序运行结果实验内 intn =;包问题的算法思想:将前 i 个物品放入容量容为 w 的背包中的最大价值。
有如下两种情况:、①若当前物品的重量小于当前可放入的重量,便可考虑是上否要将本件物品放入背包中或者将背包中的某些物品拿出机来再将当前物品放进去;放进去前需要比较(不放这个物调品的价值)和(这个物品的价值放进去加上当前能放的总试重量减去当前物品重量时取i-1 个物品是的对应重量时候程的最高价值),如果超过之前的价值,可以直接放进去,反序之不放。
棋盘覆盖实验报告
棋盘覆盖实验报告棋盘覆盖实验报告引言:棋盘覆盖是一项经典的数学问题,也是计算机科学中常见的算法设计题目。
通过这个实验,我们可以深入了解棋盘覆盖问题的背景、原理和解决方法。
本文将详细介绍实验的目的、实验过程和实验结果,并对实验中遇到的问题进行探讨和分析。
一、实验目的棋盘覆盖问题是指如何用特殊形状的骨牌覆盖一个给定大小的棋盘,使得每个格子都被覆盖且不重叠。
本实验的目的是通过实际操作,理解棋盘覆盖问题的基本概念和解决方法,并通过实验结果验证算法的正确性。
二、实验过程1. 准备工作在实验开始之前,我们需要准备一个大小为2^n * 2^n的棋盘,以及L型骨牌。
棋盘可以用纸板或者绘图软件制作,L型骨牌可以用纸板剪切而成。
确保棋盘和骨牌的大小相匹配,并将骨牌标记为不同的编号以便于辨认。
2. 实验步骤(1)将棋盘分成4个大小相等的子棋盘,每个子棋盘的大小为2^(n-1) *2^(n-1)。
(2)在四个子棋盘中的一个上放置一个特殊的L型骨牌,使得骨牌覆盖子棋盘的中心格。
(3)递归地将剩下的三个子棋盘分别覆盖。
(4)重复步骤(2)和(3),直到棋盘被完全覆盖。
三、实验结果经过实验,我们成功地完成了棋盘覆盖。
通过观察实验结果,我们可以发现每个骨牌都被正确地放置在了棋盘上,且每个格子都被覆盖且不重叠。
这验证了我们所使用的算法的正确性。
四、问题探讨和分析在实验过程中,我们遇到了一些问题,对这些问题进行探讨和分析有助于更好地理解棋盘覆盖问题。
1. 子棋盘的划分问题在实验中,我们将棋盘分成了四个子棋盘,每个子棋盘的大小都是原棋盘的一半。
这种划分方式是否合理?是否存在其他划分方式?通过思考和尝试,我们可以发现,将棋盘划分为其他数量的子棋盘也是可行的,但是划分后的子棋盘大小必须是2的幂次方。
2. 骨牌的放置问题在实验中,我们使用了特殊的L型骨牌进行覆盖。
这种骨牌是否是唯一的选择?是否存在其他类型的骨牌可以完成棋盘覆盖?通过思考和实验,我们可以发现,除了L型骨牌,还存在其他形状的骨牌可以完成棋盘覆盖,但是它们的形状和数量都是有限的。
算法实验报告范文
算法实验报告范文《算法设计与分析》实验报告班级姓名学号年月日目录实验一二分查找程序实现…………………………………………………………………03页实验二棋盘覆盖问题(分治法).…………………………………………………………08页实验三0-1背包问题的动态规划算法设计……………………………………………….11页实验四背包问题的贪心算法………………………………………………………………14页实验五最小重量机器设计问题(回溯法)………………………………………………17页实验六最小重量机器设计问题(分支限界法)…………………………………………20页指导教师对实验报告的评语成绩:指导教师签字:年月日2实验一:二分查找程序实现一、实验时间:2022年10月8日,星期二,第一、二节地点:J13#328二、实验目的及要求目的:1、用c/c++语言实现二分搜索算法。
2、通过随机产生有序表的方法,测出在平均意义下算法比较次数随问题规模的变化曲线,并作图。
三、实验环境平台:Win732位操作系统开发工具:Codeblock10.05四、实验内容对已经排好序的n个元素a[0:n-1],现在要在这n个元素中找出一特定元素某。
五、算法描述及实验步骤算法描述:折半查找法也称为二分查找法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用O(logn)完成搜索任务。
它的基本思想是,将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的某作比较,如果某=a[n/2]则找到某,算法终止。
如果某a[n/2],则我们只要在数组a的右半部继续搜索某。
二分搜索法的应用极其广泛,而且它的思想易于理解。
确定算法复杂度基本步骤:1、首先设定问题规模n;2、随即产生递增数列;3、在n个有序数中随机取一个作为待查找量,搜索之;4、记录查找过程中的比较次数,再次生成新的有序表并查找,记录查找次数,每个数组重复10次;5、改变问题规模n重复上述步骤2~4,n取100、200……1000;6、依实验数据作图,并与理论图作比较;7、二分搜索算法平均查找次数:问题规模为n时,平均查找次数为:A(n)=Int(logn)+1/2//Int()函数为向下取整3即二分搜索算法对于含有n个数据的有序表L平均作了约Int(logn)+1/2次的查找操作。
算法设计与分析实验报告棋盘覆盖问题
算法设计与分析实验报告棋盘覆盖问题贵州大学计算机科学与技术学院计算机科学与技术系上机实验报告课程名称:算法设计与分析班级:信计101班实验日期:2013-9-30 姓名: 张胜学号:1007010162 指导教师:程欣宇实验序号:一实验成绩: 一、实验名称分治算法实验 - 棋盘覆盖问题二、实验目的及要求1、熟悉递归算法编写;2、理解分治算法的特点;3、掌握分治算法的基本结构。
三、实验环境Visual C++四、实验内容根据教材上分析的棋盘覆盖问题的求解思路,进行验证性实验;要求完成棋盘覆盖问题的输入、分治求解、输出。
有余力的同学尝试消去递归求解。
五、算法描述及实验步骤分治算法原理:分治算法将大的分解成形状结构相同的子问题,并且不断递归地分解,直到子问题规模小到可以直接求解。
棋盘覆盖问题描述:在一个2k x 2k个方格组成的棋盘中恰有一个方格与其他的不同称为特殊方格,想要求利用四种L型骨牌(每个骨牌可覆盖三个方格)不相互重叠覆盖的将除了特殊方格外的其他方格覆盖。
实验步骤:1、定义用于输入和输出的数据结构;2、完成分治算法的编写;3、测试记录结构;4、有余力的同学尝试不改变输入输出结构,将递归消除,并说明能否不用栈,直接消除递归,为什么,六、调试过程及实验结果实验运行结果:七、总结通过本次实验,我更深的理解了递归和分治策略。
代码是书上的算法,加上主函数就行了,用的是C语言编写,很长时间没用了,感觉有点生疏。
实验结果有点问题,就是覆盖棋盘时,并不是按照1,2,3….的字符顺序,而是按照很乱的顺序输出字符,这个我不知道怎么解决,就没解决。
八、附录#include "stdio.h"#include "conio.h"int board[8][8] ={{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0 ,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}};int tile=0;void chessBoard(int tr, int tc, int dr, intdc, int size){int t=tile++,s=size/2;if (size==1) return;if (dr<tr+s&&dc<tc+s)chessBoard(tr,tc,dr,dc,s);else {board[tr+s-1][tc+s-1]=t;chessBoard(tr,tc,tr+s-1,tc+s-1,s);}if(dr <tr+s && dc >= tc+s)chessBoard(tr,tc+s,dr,dc,s);else {board[tr+s-1][tc+s]=t;chessBoard(tr,tc+s,tr+s-1,tc+s,s);} if(dr >= tr+s&&dc<tc+s)chessBoard(tr+s,tc,dr, dc,s);else {board[tr+s][tc+s-1]=t;chessBoard(tr+s,tc,tr+s,tc+s-1,s);} if(dr >= tr+s &&dc>=tc+s) chessBoard(tr+s,tc+s,dr,dc,s);else {board[tr+s][tc+s]=t;chessBoard(tr+s,tc+s,tr+s,tc+s,s);} }main(){int i ,j;chessBoard(0,0,5,5,8);for(i=0;i <8;i++){for( j=0;j <8;j++) {if(board[i][j]<10)printf("0");printf("%d",board[i][j]);printf(" ");}printf( "\n"); } getchar();}。
背包问题实验报告
背包问题实验报告《背包问题实验报告》背包问题是一个经典的组合优化问题,它在计算机科学和运筹学领域被广泛应用。
在这个问题中,我们需要从一组物品中选择一些放入背包,使得它们的总重量不超过背包的承载能力,同时价值最大化。
在本实验中,我们将探讨不同算法在解决背包问题时的表现,并分析它们的优缺点。
首先,我们使用了贪心算法来解决背包问题。
贪心算法的基本思想是每次选择当前最有利的物品放入背包,直到背包装满或者没有物品可选。
虽然贪心算法在一些情况下能够得到较好的解,但它并不保证能够得到最优解,因为它只考虑了局部最优解而没有综合考虑所有可能的选择。
接着,我们使用了动态规划算法来解决背包问题。
动态规划算法通过将问题分解成子问题,并保存子问题的解来避免重复计算,从而得到最优解。
动态规划算法在解决背包问题时能够得到最优解,但它需要额外的空间来保存子问题的解,因此在处理大规模问题时可能会消耗较多的内存。
最后,我们使用了回溯算法来解决背包问题。
回溯算法通过不断尝试所有可能的选择,并在满足条件时继续向下搜索,直到找到解或者搜索完所有可能的选择。
回溯算法能够得到最优解,但它的时间复杂度较高,因为它需要尝试所有可能的选择。
通过实验我们发现,不同算法在解决背包问题时有各自的优缺点。
贪心算法简单快速,但不能保证得到最优解;动态规划算法能够得到最优解,但需要额外的空间;回溯算法能够得到最优解,但时间复杂度较高。
因此,在实际应用中需要根据具体情况选择合适的算法来解决背包问题。
综上所述,通过本实验我们对背包问题的解决算法有了更深入的了解,并且能够根据具体情况选择合适的算法来解决实际问题。
希望本实验能够对相关领域的研究和应用有所帮助。
棋盘覆盖实验报告
int x_pos;//特殊点横坐标
int y_pos;//特殊点竖坐标
Container p;
public MyChessBoard() {
super();
x_pos = 0;
y_pos = 0;
dimen = 0;
setTitle("棋盘覆盖");
setBackground(Color.YELLOW);
y = 0;}setLocation(x, y);}public void actionPerformed(ActionEvent e) {
if(e.getActionCommand()=="退出") {
System.exit
(0);}else if(e.getActionCommand()=="开始") {
x_pos = (int)(dimen*Math.random());//随机生成特殊点位置
y_pos = (int)(dimen*Math.random());
p.setLayout(new GridLayout(dimen, dimen));
System.out.println(x_pos+","+y_pos);
/**** @authorxxxx
*/
public class FenZi {
public static void main(String args[]){new MyChessBoard();}}
class MyChessBoard extends JFrame implements ActionListener {
for(int j=0; j<board[i].length; j++) {
动态规划方案解决算法背包问题实验报告含源代码
动态规划方案解决算法背包问题实验报告含嘿,大家好!今天我来给大家分享一个相当有趣的编程问题——背包问题。
这可是算法领域里的经典难题,也是体现动态规划思想的好例子。
我会用我10年的方案写作经验,给大家带来一份详细的实验报告,附带哦!让我简单介绍一下背包问题。
假设你是一个盗贼,要盗取一个博物馆里的宝贝。
博物馆里有n个宝贝,每个宝贝都有它的价值v和重量w。
你有一个承重为W的背包,你希望放入背包的宝贝总价值最大,但总重量不能超过背包的承重。
这个问题,就是我们要解决的背包问题。
一、算法思路1.创建一个二维数组dp,dp[i][j]表示前i个宝贝放入一个承重为j的背包中,能达到的最大价值。
2.初始化dp数组,dp[0][j]=0,因为如果没有宝贝,那么无论背包承重多少,价值都是0。
3.遍历每个宝贝,对于每个宝贝,我们有两种选择:放入背包或者不放入背包。
4.如果不放入背包,那么dp[i][j]=dp[i-1][j],即前i-1个宝贝放入一个承重为j的背包中,能达到的最大价值。
5.如果放入背包,那么dp[i][j]=dp[i-1][j-w[i]]+v[i],即前i-1个宝贝放入一个承重为j-w[i]的背包中,加上当前宝贝的价值。
6.dp[i][j]取两种情况的最大值。
二、defknapsack(W,weights,values,n):dp=[[0for_inrange(W+1)]for_inrange(n+1)]foriinrange(1,n+1):forjinrange(1,W+1):ifj>=weights[i-1]:dp[i][j]=max(dp[i-1][j],dp[i-1][j-weights[i-1]]+values[i -1])else:dp[i][j]=dp[i-1][j]returndp[n][W]测试数据W=10weights=[2,3,4,5]values=[3,4,5,6]n=len(values)输出结果max_value=knapsack(W,weights,values,n)print("最大价值为:",max_value)三、实验结果分析通过上面的代码,我们可以得到最大价值为15。
背包问题和TSP问题算法报告
算法报告班级: 140710班组员: 14071006 魏泽琳14071008 田恬14071019 黄婧婧14071021 宋蕊14071026 于婷雯指导老师:徐旭东广义背包问题一、问题描述广义背包问题的描述如下:给定载重量为M的背包和n种物品,每种物品有一定的重量和价值,现在需要设计算法,在不超过背包载重量的前提下,巧妙选择物品,使得装入背包的物品的总价值最大化。
规则是,每种物品均可装入背包多次或不装入(但不能仅装入物品的一部分)。
请用数学语言对上述背包问题加以抽象,在此基础上给出动态规划求解该问题的递归公式。
要求对所给公式中的符号意义加以详细说明,并简述算法的求解步骤。
用一种你熟悉的程序设计语言加以实现。
二、基本思路1、01背包问题在讨论广义背包问题前应该先讨论最基础的01背包问题。
这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
用子问题定义状态:即F[i][m]表示前i件物品恰放入一个重量为m的背包可以获得的最大价值。
其状态转移方程是:F[i][m]=max{F[i−1][m],F[i−1][m−wi]+Ci}}这个方程是解决背包问题的关键点,基本上所有跟背包相关的问题的方程都是由它衍生出来的。
所以有必要解释一下:“将前i件物品放入容量为m的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只和前i−1件物品相关的问题。
如果不放第i件物品,那么问题就转化为“前i−1件物品放入容量为v的背包中”,价值为F[i−1][m];如果放第i件物品,那么问题就转化为“前i−1件物品放入剩下的容量为m−wi 的背包中”,此时能获得的最大价值就是F[i−1][m−wi]再加上通过放入第i件物品获得的价值Ci。
最优解的函数从方程中能得出:F[i][m]=F[i-1][m](当第i个物品不装入)F[i][m]>F[i-1][m](当第i个物品装入)以上是有关01背包的讨论,现在讨论广义背包的问题。
棋盘覆盖实验报告
实验报告课程名称算法分析与设计实验项目名称棋盘覆盖算法设计与实现班级与班级代码14251102202实验室名称(或课室)实验楼802 专业计算机科学与技术任课教师李绍华学号:14251102202姓名:陈晓俊实验日期:2016年10月27日广东商学院教务处制姓名实验报告成绩评语:指导教师(签名)年月日说明:指导教师评分后,实验报告交院(系)办公室保存。
一、实验目的1、理解算法的概念2、实现棋盘化以及棋盘覆盖3、理解递归与分治策略算法4、能够用Java语言实现该算法二、实验设备硬件:计算机一台软件:Windows 7操作系统、eclipse Java编程软件三、问题与算法描述1、问题描述在一个2^k×2^k (k≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格,且称该棋盘为一个特殊棋盘。
在棋盘覆盖问题中,要用4种不同形态的L型骨牌覆盖给定的特异盘上除特殊方格以外所有方格,且任何2个L型骨牌不得重叠覆盖。
2、算法描述当k>0时 将2^k×2^k 棋盘分割为4个2k-1×2k-1 子棋盘。
特殊方格必位于4个较小子棋盘之一中,其余3个子棋盘中无特殊方格。
为了将这3个无特殊方格的子棋盘转化为特殊棋盘可以用一个L型骨牌覆盖,从而将原问题转化为4个较小规模的棋盘覆盖问题。
递归地使用这种分割直至棋盘简化为棋盘1×1。
3、算法时间复杂性分析从算法的分割策略可知,此算法的时间复杂度如下递归方程所示:)1()1(40)1({)(>+-==k o k T k o k T解此递归方程可得:)4()(k o k T =。
由于覆盖2^k ×2^k 棋盘所需的L 型骨牌个数为3/14k )(-,所以这个算法是一个渐进意义的最优算法。
四、实验结果 1、当k=0时:2、当k>0时: 例如k=3时:例如k=5时:。
算法设计与分析实验报告-背包问题
算法设计与分析实验报告一、实验内容:给定n 种物品和一背包。
物品i 的重量是w i ,其价值为v i ,背包的容量为C 。
问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?二、算法思想与设计描述:(一)基本算法:1、使用动态规划算法计算最优值,递归式如下,m(i ,j)是背包容量为j ,可选择物品为i ,i+1,…,n 时0-1背包问题的最优值具体代码:for(i=1; i<=num; i++)for(j=1; j<=C; j++){int temp = value[i -1][j -goods[i].weight]+goods[i].value;if(j>=goods[i].weight && temp > value[i -1][j])value[i][j] = temp;elsevalue[i][j] = value[i -1][j];}2、逆推得出装入背包的物品:j = C;for(i=num; i>=1; i --){if(value[i][j] > value[i -1][j]){judge[i] = 1;j -= goods[i].weight;}}(二)改进算法:1、求最大价值:i i i i w j w j j i m v w j i m j i m j i m <≤≥⎩⎨⎧+-=0),1-(}),1-(),,1-(max{),(具体代码:for(i=0; i<MAXNUM; i++){for(j=0; j<MAXNUM; j++){p[i][j].weight = 0;p[i][j].value = 0;q[i][j].weight = 0;q[i][j].value = 0;}}for(i=0; i<=num-1; i++){j = 0;//计算q集合的值while(j == 0 || (j>0 && p[i][j].weight!=0)){q[i][j].weight = p[i][j].weight + goods[i+1].weight;q[i][j].value = p[i][j].value + goods[i+1].value;j++;}m = 1; k = 0; j = 1;//复制i层的p、q到i+1层的p中并按重量由小到大排序while(p[i][j].weight!=0 && q[i][k].weight!=0){if(p[i][j].weight <= q[i][k].weight){p[i+1][m] = p[i][j];j++;}else{p[i+1][m] = q[i][k];k++;}m++;}while(p[i][j].weight != 0)//i层的p还没有复制结束{p[i+1][m] = p[i][j];j++;m++;}while(q[i][k].weight != 0)//i层的p还没有复制结束{p[i+1][m] = q[i][k];k++;m++;}k = 1;while(p[i+1][k].weight)//删除集合A、集合B中的元素{if((p[i+1][k].value<p[i+1][k-1].value) || (p[i+1][k].weight > C)){j = k;while(p[i+1][j].weight){p[i+1][j] = p[i+1][j+1];j++;}}elsek++;}}max_value=p[i][k-1].value;2、逆推得出最优装法:•初设i=n•比较p[i](j1,v1)与p[i-1](j2,v2)的最后一个元素,如果不同,则第i个一定被选了,且下一次i为(j1-wi,v1-vi)第一次出现的位置;如果相同则i——;•循环执行上述步骤直到i=0为止//逆推得到最优装法i = num;while(i){j = 1; k = 1;while(p[i][j].weight)j++;while(p[i-1][k].weight)k++;j--; k--;if(p[i][j].value != p[i-1][k].value){judge[i] = 1;//第i个被选中了if(i == 1)i--;int last_weight = p[i][j].weight-goods[i].weight;int last_value = p[i][j].value - goods[i].value;m = 1;while(i>1 && m<=num)//找到下一个i{j = 1;while(p[m][j].weight){if(p[m][j].weight == last_weight && p[m][j].value == last_value){i = m;break;}else{j++;}}if(i == m)break;m++;}}elsei--;}三、测试说明:1、基本算法算法复杂度:O(nC)2、改进算法:算法复杂度:O(min{nC, 2^n})四、实验总结:动态规划算法可以避免普通递归算法在某些问题上的重复计算,是一种聪明的递归。
实验报告-分支限界法01背包
《算法设计与分析》实验报告六学号: 1004091130 姓名:金玉琦日期: 2011-11-17 得分:一、实验内容:运用分支限界法解决0-1背包问题。
二、所用算法的基本思想及复杂度分析:分支限界法分支限界法按广度优先策略遍历问题的解空间树, 在遍历过程中, 对已经处理的每一个结点根据限界函数估算目标函数的可能取值, 从中选取使目标函数取得极值的结点优先进行广度优先搜索, 从而不断调整搜索方向, 尽快找到问题的解。
因为限界函数常常是基于问题的目标函数而确定的, 所以, 分支限界法适用于求解最优化问题。
0-1背包问题1)基本思想给定n 种物品和一个容量为C 的背包, 物品i 的重量是W i, 其价值为V i, 0/ 1 背包问题是如何选择装入背包的物品(物品不可分割) , 使得装入背包中物品的总价值最大,一般情况下, 解空间树中第i 层的每个结点, 都代表了对物品1~i 做出的某种特定选择, 这个特定选择由从根结点到该结点的路径唯一确定: 左分支表示装入物品, 右分支表示不装入物品。
对于第i 层的某个结点, 假设背包中已装入物品的重量是w, 获得的价值是v, 计算该结点的目标函数上界的一个简单方法是把已经装入背包中的物品取得的价值v, 加上背包剩余容量W - w 与剩下物品的最大单位重量价值vi + 1/ wi + 1的积,于是,得到限界函数:u b = v + ( W - w) × ( vi + 1/ wi + 1 )根据限界函数确定目标函数的界[ down , up],然后, 按照广度优先策略遍历问题的空间树。
2)复杂度分析时间复杂度是O(2n);三、源程序及注释:#include<iostream>#include<cstdio>#include<conio.h>#include<iomanip>using namespace std;int *x;struct node{//结点表结点数据结构node *parent,//父结点指针*next; //后继结点指针int level,//结点的层bag,//节点的解cw,//当前背包装载量cp;//当前背包价值float ub; //结点的上界值};class Knap{private:struct node *front, //队列队首*bestp,*first; //解结点、根结点int *p,*w,n,c,*M;//背包价值、重量、物品数、背包容量、记录大小顺序关系long lbestp;//背包容量最优解public:void Sort();Knap(int *pp,int *ww,int cc,int nn);~Knap();float Bound(int i,int cw,int cp);//计算上界限node *nnoder(node *pa,int ba,float uub);//生成一个结点 ba=1生成左节点 ba=0生成右节点void addnode(node *nod);//将结点添加到队列中void deletenode(node *nod);//将结点队列中删除struct node *nextnode(); //取下一个void display(); //输出结果void solvebag(); //背包问题求解};Knap::Knap(int *pp,int *ww,int cc,int nn){int i;n=nn;c=cc;p=new int[n];w=new int[n];M=new int[n];for(i=0;i<n;i++){p[i]=pp[i];w[i]=ww[i];M[i]=i;}front=new node[1];front->next=NULL;lbestp=0;bestp=new node[1];bestp=NULL;Sort();}Knap::~Knap(){delete []first;delete []front;delete []bestp;delete []p;delete []w;}float Knap::Bound(int i,int cw,int cp){// 计算上界int cleft=c-cw;float b=(float)cp;while (i<n&&w[i]<=cleft){cleft-=w[i];b+=p[i];i++;}if (i<n) b+=1.0*p[i]/w[i]*cleft;return b;}node * Knap::nnoder(struct node *pa,int ba,float uub) {//生成一个新结点node * nodell=new(node);nodell->parent=pa;nodell->next=NULL;nodell->level=(pa->level)+1;nodell->bag=ba;nodell->ub=uub;if(ba==1){nodell->cw=pa->cw+w[pa->level];nodell->cp=pa->cp+p[pa->level] ;}else{nodell->cw=pa->cw;nodell->cp=pa->cp;}return(nodell);}void Knap::addnode(node *no){//将结点加入优先队列node *p=front->next,*next1=front;float ub=no->ub;while(p!=NULL){if(p->ub<ub){no->next=p;next1->next=no;break;}next1=p;p=p->next;}if(p==NULL){next1->next=no;}}node *Knap::nextnode(){//取上限最大结点node *p=front->next;front->next=p->next;return(p);}void Knap::Sort(){int i,j,k,kkl;float minl;for(i=1;i<n;i++){minl=1.0*p[i]/w[i];k=0;for(j=1;j<=n-i;j++){if(minl<1.0*p[j]/w[j]){minl=1.0*p[j]/w[j];swap(p[k],p[j]);swap(w[k],w[j]);swap(M[k],M[j]);k=j;}}}}void Knap::display(){int i;cout<<"最大价值是:"<<lbestp<<endl;for(i=n;i>=1;i--){x[M[i-1]]=bestp->bag;bestp=bestp->parent;}cout<<"变量值为:"<<endl;for(i=1;i<=n;i++)cout<<"x("<<setw(2)<<i<<")="<<x[i-1]<<endl;}void Knap::solvebag(){//背包问题求解int i;float ubb;node *aa;first=new node[1]; //根结点first->parent=NULL;first->next=NULL;first->level=0;first->cw=0;first->cp=0;first->bag=0;ubb=Bound(0,0,0);first->ub=ubb;front->next=first;while(front->next!=NULL){aa=nextnode();i=aa->level;if(i==n-1){if(aa->cw+w[i]<=c&&(long)(aa->cp+p[i])>lbestp){lbestp=aa->cp+p[i];bestp=nnoder(aa,1,(float)lbestp);}if((long)(aa->cp)>lbestp){lbestp=aa->cp;bestp=nnoder(aa,0,(float)lbestp);}}if(i<n-1){if(aa->cw+w[i]<=c&&Bound(i+1,aa->cw+w[i],aa->cp+p[i])>(float)lbestp){ubb=Bound(i,aa->cw+w[i],aa->cp+p[i]);addnode(nnoder(aa,1,ubb));}ubb=ubb=Bound(i,aa->cw,aa->cp);if(ubb>lbestp)addnode(nnoder(aa,0,ubb));}}display();}void main(){int c,n;int i=0;int *p;int *w;cout<<"请输入背包容量:"<<endl;cin>>c;cout<<"请输入物品数:"<<endl;cin>>n;x=new int[n];p=new int[n];w=new int[n];cout<<"请输入"<<n<<"个物品的重量:"<<endl;for(i=0;i<n;i++)cin>>w[i];cout<<"请输入"<<n<<"个物品价值:"<<endl;for(i=0;i<n;i++)cin>>p[i];x=new int[n];Knap knbag(p,w,c,n);knbag.solvebag();getch();return;}四、运行输出结果:五、调试和运行程序过程中产生的问题、采取的措施及获得的相关经验教训:解决该问题首先要确定一个合适的限界函数数, 并根据限界函数确定目标函数的界[down,up],然后按照广度优先策略遍历问题的解空间树,在分支结点上,依次搜索该结点的所有孩子结点,分别估算这些孩子结点的目标函数的可能取值,如果某孩子结点的目标函数可能取得的值超出目标函数的界, 则将其丢弃, 因为从这个结点生成的解不会比目前已经得到的解更好; 否则, 将其加入待处理结点表中。
背包问题问题实验报告(3篇)
第1篇一、实验目的1. 理解背包问题的基本概念和分类。
2. 掌握不同背包问题的解决算法,如0-1背包问题、完全背包问题、多重背包问题等。
3. 分析背包问题的复杂度,比较不同算法的效率。
4. 通过实验验证算法的正确性和实用性。
二、实验环境1. 操作系统:Windows 102. 编程语言:Python3.73. 开发工具:PyCharm4. 实验数据:随机生成的背包物品数据三、实验内容1. 0-1背包问题(1)问题描述:给定n个物品,每个物品的重量为w[i],价值为v[i],背包的容量为C。
求将哪些物品装入背包,使得背包内物品的总价值最大。
(2)解决算法:动态规划法(3)实验步骤:a. 初始化一个二维数组dp[n+1][C+1],其中dp[i][j]表示前i个物品在容量为j 的背包中的最大价值。
b. 遍历每个物品,对于每个容量,根据物品的重量和价值计算dp值。
c. 返回dp[n][C],即为最大价值。
2. 完全背包问题(1)问题描述:给定n个物品,每个物品的重量为w[i],价值为v[i],背包的容量为C。
求将哪些物品装入背包,使得背包内物品的总价值最大,且每个物品可以重复取。
(2)解决算法:动态规划法(3)实验步骤:a. 初始化一个一维数组dp[C+1],其中dp[j]表示容量为j的背包的最大价值。
b. 遍历每个物品,对于每个容量,根据物品的重量和价值更新dp值。
c. 返回dp[C],即为最大价值。
3. 多重背包问题(1)问题描述:给定n个物品,每个物品的重量为w[i],价值为v[i],背包的容量为C。
每个物品有无限个,求将哪些物品装入背包,使得背包内物品的总价值最大。
(2)解决算法:动态规划法(3)实验步骤:a. 初始化一个一维数组dp[C+1],其中dp[j]表示容量为j的背包的最大价值。
b. 遍历每个物品,对于每个容量,根据物品的重量和价值更新dp值。
c. 返回dp[C],即为最大价值。
四、实验结果与分析1. 0-1背包问题实验结果显示,在背包容量为100时,最大价值为298。
背包问题实验报告
一、实验背景背包问题是组合优化领域中经典的NP难问题,具有广泛的应用背景。
背包问题是指在一个背包的容量限制下,如何从一组物品中选择一部分物品,使得所选物品的总价值最大。
背包问题分为0-1背包问题、完全背包问题、多重背包问题等。
本实验旨在比较不同背包问题的算法性能,为实际应用提供参考。
二、实验目的1. 比较不同背包问题的算法性能;2. 分析不同算法的时间复杂度和空间复杂度;3. 为实际应用选择合适的背包问题算法。
三、实验环境1. 操作系统:Windows 102. 编程语言:Python3.73. 数据集:随机生成的背包问题数据集四、实验方法1. 实验数据:生成不同规模的背包问题数据集,包括物品数量、背包容量和物品价值;2. 算法:比较以下背包问题的算法性能:(1)0-1背包问题的动态规划算法;(2)完全背包问题的动态规划算法;(3)多重背包问题的动态规划算法;3. 性能指标:计算每个算法的运行时间、空间复杂度和最优解价值。
五、实验结果与分析1. 0-1背包问题(1)动态规划算法算法实现:根据0-1背包问题的状态转移方程,实现动态规划算法。
运行时间:随背包容量和物品数量的增加,运行时间呈指数增长。
空间复杂度:O(n×C),其中n为物品数量,C为背包容量。
最优解价值:根据动态规划算法,得到最优解价值为198。
(2)回溯法算法实现:根据0-1背包问题的状态转移方程,实现回溯法。
运行时间:随背包容量和物品数量的增加,运行时间呈指数增长。
空间复杂度:O(n×C),其中n为物品数量,C为背包容量。
最优解价值:根据回溯法,得到最优解价值为198。
2. 完全背包问题(1)动态规划算法算法实现:根据完全背包问题的状态转移方程,实现动态规划算法。
运行时间:随背包容量和物品数量的增加,运行时间呈线性增长。
空间复杂度:O(n×C),其中n为物品数量,C为背包容量。
最优解价值:根据动态规划算法,得到最优解价值为300。
棋盘覆盖实验报告心得(3篇)
第1篇一、实验背景棋盘覆盖实验是计算机科学中一个经典的算法问题,旨在研究如何用最少数量的棋子覆盖整个棋盘。
这个实验不仅考验了我们对算法和数据结构的理解,还锻炼了我们的逻辑思维和编程能力。
在本实验中,我选择了使用回溯算法来解决棋盘覆盖问题,以下是我在实验过程中的心得体会。
二、实验目的1. 理解棋盘覆盖问题的背景和意义;2. 掌握回溯算法的基本原理和应用;3. 提高编程能力和逻辑思维能力;4. 分析不同算法的优缺点,为实际应用提供参考。
三、实验过程1. 确定问题模型棋盘覆盖问题可以抽象为一个二维数组,其中每个元素代表棋盘上的一个格子。
我们需要使用棋子(如皇后)来覆盖整个棋盘,使得每个格子都被至少一个棋子覆盖。
在本实验中,我们选择使用N皇后问题作为棋盘覆盖问题的子问题。
2. 设计算法为了解决棋盘覆盖问题,我们可以采用回溯算法。
回溯算法的基本思想是从一个解空间中搜索解,当找到一个解时,将其输出;当发现当前解不满足条件时,回溯到上一个状态,尝试其他可能的解。
具体步骤如下:(1)初始化棋盘,将所有格子设为未覆盖状态;(2)从第一行开始,尝试将棋子放置在该行第一个格子;(3)判断放置棋子后是否满足约束条件,如冲突、越界等;(4)如果满足约束条件,将该格子设为已覆盖状态,继续放置下一行棋子;(5)如果当前行已放置完棋子,检查是否覆盖了整个棋盘;(6)如果覆盖了整个棋盘,输出解;否则,回溯到上一个状态,尝试其他可能的解。
3. 编写代码根据上述算法,我使用Python语言实现了棋盘覆盖问题的回溯算法。
在代码中,我定义了一个二维数组来表示棋盘,并实现了放置棋子、检查约束条件、回溯等功能。
4. 实验结果与分析通过实验,我发现以下结论:(1)随着棋盘大小的增加,回溯算法的搜索空间也随之增大,导致算法的运行时间显著增加;(2)在解决N皇后问题时,当棋盘较大时,回溯算法的效率较低;(3)通过优化算法,如剪枝,可以提高算法的效率。
贪心算法实现背包问题算法设计与分析实验报告
算法设计与分析实验报告实验名称 贪心算法实现背包问题 评分 实验日期 年 月 日 指导教师 姓名 专业班级 学号一.实验要求1. 优化问题有n个输入,而它的解就由这n个输入满足某些事先给定的约束条件的某个子集组 成,而把满足约束条件的子集称为该问题的可行解。
可行解一般来说是不唯一的。
那些使目标函数取极值(极大或极小)的可行解,称为最优解。
2.贪心法求优化问题算法思想:在贪心算法中采用逐步构造最优解的方法。
在每个阶段,都作出一个看上去最优的决策(在一定的标准下)。
决策一旦作出,就不可再更改。
作出贪心决策的依据称为贪心准则(greedy criterion)。
3.一般方法1)根据题意,选取一种量度标准。
2)按这种量度标准对这n个输入排序3)依次选择输入量加入部分解中。
如果当前这个输入量的加入,不满足约束条件,则不把此输入加到这部分解中。
procedure GREEDY(A,n) /*贪心法一般控制流程*///A(1:n)包含n个输入//solutions←φ //将解向量solution初始化为空/for i←1 to n dox←SELECT(A)if FEASIBLE(solution,x)then solutions←UNION(solution,x)endifrepeatreturn(solution)end GREEDY4. 实现典型的贪心算法的编程与上机实验,验证算法的时间复杂性函数。
二.实验内容1. 编程实现背包问题贪心算法。
通过具体算法理解如何通过局部最优实现全局最优,并验证算法的时间复杂性。
2.输入5个的图的邻接矩阵,程序加入统计prim算法访问图的节点数和边数的语句。
3.将统计数与复杂性函数所计算比较次数比较,用表格列出比较结果,给出文字分析。
三.程序算法1. 背包问题的贪心算法procedure KNAPSACK(P,W,M,X,n)//P(1:n)和W(1;n)分别含有按P(i)/W(i)≥P(i+1)/W(i+1)排序的n件物品的效益值和重量。
案例4:背包问题
案例:背包问题有一个徒步旅行者,已知他能承受的旅行背包的重量不超过a (kg )。
设有n 种物品可供他选择装入背包,这n 种物品分别编号为1,2,…,n 。
其中第i 种物品每件的重量为a i (kg ),其使用价值(指一件第i 种物品对旅行者来说所带来的好处的一种数量指标)为c i (i =1,2,…,n )。
问这位旅行者应如何选择携带这n 种物品的件数,使得总价值最大?⏹ 分析:这是一个组合最优化问题,易将此问题归结为一个线性整数规划问题。
⏹ 建立线性规划模型【建立线性规划模型】设旅行者选择携带第i 种物品的件数为i x ,不难看出,背包问题可以归结为如下的线性规划问题:11 max s.t. 01,2,ni ii n i i i i z c x a x ax i n===≤≥=∑∑且整,,⏹ 建立动态规划模型 【建立动态规划模型】设把可装入背包的物品种类分为n 个阶段。
在第i 阶段先装入前i 种物品(i =1,2,…,n )。
在第i 阶段开始时,把旅行者背包中允许装入前i 种物品的总重量作为状态变量,设为y 。
装入每种物品的件数x i (i =1,2,…,n )为各阶段的决策变量。
变量说明:设()k f y 等于当背包中允许装入物品的总重量不超过y 和只允许装入前k 种物品采用最优策略时的最大使用价值。
(k =1,2,…,n )。
则11()max (1,2,,)k i i i k k i i i a x y f y c x k n ==≤==∑∑并且当k =n ,y =a 时,有11()max n i i i nn i i i a x a f a c x ==≤=∑∑ 显然()n f a 也就是上述线性规划模型的最优解。
把上式转化为递归方程: (属于前向算法){}1111010()max ()max () i k k y x a k k k k k k y x a f y c x f y c x f y a x ⎢⎥≤≤⎢⎥⎣⎦-⎢⎥≤≤⎢⎥⎣⎦=⎧⎪⎪⎨=+-⎪⎪⎩其中k x 为非负整数。
算法背包问题(课堂参考)
实验题目:背包问题实验目的:掌握动态规划、贪心算法的原理,并能够按其原理编程实现解决背包问题,以加深对上述方法的理解。
实验内容:一个旅行者准备随身携带一个背包. 可以放入背包的物品有n 种, 每种物品的重量和价值分别为 wj , vj . 如果背包的最大重量限制是 b, 怎样选择放入背包的物品以使得背包 的价值最大?目标函数:约束条件:线性规划问题 由线性条件约束的线性函数取最大或最小的问题整数规划问题 线性规划问题的变量 xj 都是非负整数Fk(y):装前 k 种物品, 总重不超过 y, 背包的最大价值i(k,y):装前 k 种物品, 总重不超过 y, 背包达最大价值时装入物品的最大标号递推方程、边界条件、标记函数实例计算:v1 = 1, v2 = 3, v3 = 5, v4 = 9, w1 = 2, w2 = 3, w3 = 4, w4 = 7,b = 10Fk(y) 的计算表如下:K/y 1 2 3 4 5 6 7 8 9 101 0 1 12 23 34 4 52 0 13 34 6 6 7 9 93 0 1 3 5 5 6 8 10 10 114 0 1 35 56 9 10 10 12实验步骤: 1、分析题目;N ,max 11∈≤∑∑==j n j j j n j j j x b x wx v 0)()(0,0)0(,0,0)(})(),(max{)(11101<-∞=⎥⎦⎥⎢⎣⎢=≤≤=≤≤=+-=-y y F v w y y F n k F b y y F v w y F y F y F k k k k k k k2、打开NetBeans软件,新建一个名叫 Knapsackdxj的项目,并对其进行保存;3在新建的项目下对我们所分析的题目进行编写;4、调试所编写的程序;5、运行文件,并对其进行测试,看是否正确。
实验结果:实验小结:在做本次实验之前,自己对动态规划、贪心算法的原理不是非常的理解,花了很多时间看了课本上的相关内容。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计报告课程设计名称:算法设计与分析系别:三系学生姓名:**班级:09软件(1)班学号:***********成绩:指导教师:秦川开课时间:2011-2012 学年第一学期目录一、问题描述 (3)1.普通背包问题 (3)2.棋盘覆盖问题 (3)二、问题分析 (3)1.普通背包 (3)2.棋盘覆盖 (4)三、建立数学模型 (4)1.普通背包 (4)2.棋盘覆盖 (5)四、算法设计 (5)1.普通背包 (5)2.棋盘覆盖 (6)五、算法实现(源程序) (7)1.普通背包 (7)2.棋盘覆盖 (9)六、测试分析 (11)1.普通背包 (11)2.棋盘覆盖 (14)七、结论 (16)八、参考文献 (17)一、问题描述1.普通背包问题:给定n种物品和一个背包。
物品i的重量是wi,其价值是vi,背包的容量是C。
应如何选择装入背包的物品,是得装入背包中的物品的总价值最大?在选择装入背包的物品是,对每种物品i的选择可以是物品的的一部分(即可以不是整数),而不一定要全部装入背包,1<=i<=n.2.棋盘覆盖问题:在一个(2^k) × (2^k) 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。
显然,特殊方格在棋盘中出现的位置有4^k情形,因而有4^k种不同的棋盘。
图a所示是k=2时16种棋盘中的一个。
棋盘覆盖问题要求用图b所示的4种不同形状的L型骨牌覆盖给定棋盘上除特殊棋盘方格以外的所有方格,且任何两个L型骨牌不得重叠覆盖。
二、问题分析1.普通背包:贪心算法的基本思路:从问题的某一个初始解出发逐步逼近给定的目标,每一步都作一个不可回溯的决策,尽可能地求得最好的解。
当达到某算法中的某一步不需要再继续前进时,算法停止。
这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。
则其状态转移方程便是:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。
如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。
2.棋盘覆盖:分析方法:分治的技巧在于如何划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋盘均包含一个特殊方格(这句话很重要),从而将原问题分解为规模较小的棋盘覆盖问题。
先把原始棋盘划分成4个相等的棋盘,由于棋盘只有一个特殊棋盘,所以这4个子棋盘中只有一个子棋盘包含该特殊棋盘,以便采用递归的方法求解,可以用1一个L型骨牌覆盖这3个较小棋盘的汇合处(要理解这句话),如图(c)所示。
从而将原问题转换为4个较小规模的棋盘覆盖问题。
递归使用这种划分策略,直至将棋盘分割为1*1的子棋盘。
三、建立数学模型1.普通背包://=========确定背包新的剩余容量============left=left-goods[i].w;//=========该物品所要放的量=========goods[i].X=left/goods[i].w;2.棋盘覆盖:数据结构设计:(1)棋盘:可以一个二维数组board[size][size]表示一个棋盘,其中,size = 2^k。
为了在递归处理的过程中使用同一个棋盘,将数组board设置为全局变量(2)子棋盘:子棋盘由原始棋盘数组board的行下标tr,列下标tc表示。
(3)特殊方格:用board[dr][dc]表示特殊方格,dr和dc表示该特殊方格的在二维数组board中的下标(4)L型骨牌:一个(2^k)*(2^k)的棋盘中有一个特殊方格,所以用到L型骨牌的个数为(4^k - 1)/3,将所有L型骨牌从1开始连续编号,同一个骨牌有3个方格组成,这3个方格用同一个编号。
四、算法设计1.普通背包:// 先按物品效益,重量比值做升序排列================================void Insertionsort(Good goods[],int n){int i,j;for(j=2;j<=n;j++){goods[0]=goods[j];i=j-1;while (goods[0].p>goods[i].p){goods[i+1]=goods[i];i--;}goods[i+1]=goods[0];}}// 然后再将物品放入背包=======================void bag(Good goods[],float M,int n){ 。
left=M; //========背包剩余容量{ 。
//========当该物品重量大与剩余容量跳出。
//=========确定背包新的剩余容量}if(i<=n)goods[i].X=left/goods[i].w;//=========该物品所要放的量for(j=2;j<=n;j++) //==========按物品编号做降序排列{ 。
}。
}}2.棋盘覆盖:void chessBoard(int tr, int tc, int dr, int dc, int size){。
if(dr<tr+s && dc<tc+s) //残缺方格位于左上棋盘chessBoard(tr, tc, dr, dc, s);else {board[tr+s-1][tc+s-1]=t;/ /覆盖1号三格板chessBoard(tr, tc, tr+s-1, tc+s-1, s); //覆盖其余部分}if(dr<tr+s && dc>=tc+s) //残缺棋盘位于右上棋盘chessBoard(tr, tc+s, dr, dc, s);else{board[tr+s-1][tc+s]=t; //覆盖2号三格板chessBoard(tr, tc+s, tr+s-1, tc+s, s); //覆盖其余部分}if(dr>=tr+s && dc<tc+s) //残缺方格位于左下棋盘chessBoard(tr+s, tc, dr, dc, s);else{board[tr+s][tc+s-1]=t; //覆盖3号三格板chessBoard(tr+s, tc, tr+s, tc+s-1, s); //覆盖其余部分}if(dr>=tr+s && dc>=tc+s) //残缺方格位于右下棋盘chessBoard(tr+s, tc+s, dr, dc, s);else{board[tr+s][tc+s]=t; //覆盖4号三格板chessBoard(tr+s, tc+s, tr+s, tc+s, s);//覆盖其余棋盘}五、算法实现(源程序)1.普通背包:#include <iostream.h>#include <string>using namespace std;struct Good{float p; //物品的效益float w; //物品的重量float X; //物品该放的数量int flag; //物品的编号}; //物品信息结构体//======== 按物品效益,重量比值做升序排列=============//void Insertionsort(Good goods[],int n){int i,j;for(j=2;j<=n;j++){goods[0]=goods[j];i=j-1;while (goods[0].p>goods[i].p){goods[i+1]=goods[i];i--;}goods[i+1]=goods[0];}}//========== 将物品放入背包================void bag(Good goods[],float M,int n){float left;int i,j;for(i=1;i<=n;i++)goods[i].X=0;left=M; //========背包剩余容量for(i=1;i<n;i++){ if(goods[i].w>left) //========当该物品重量大与剩余容量跳出break;goods[i].X=1;left=left-goods[i].w; //=========确定背包新的剩余容量}if(i<=n)goods[i].X=left/goods[i].w;//=========该物品所要放的量for(j=2;j<=n;j++) //==========按物品编号做降序排列{ goods[0]=goods[j];i=j-1;while (goods[0].flag<goods[i].flag){goods[i+1]=goods[i];i--;}goods[i+1]=goods[0];}cout<<"最优解为:"<<endl;for(i=1;i<=n;i++){cout<<"第"<<i<<"件物品要放:";cout<<goods[i].X<<endl;}}//============== 主函数=================//void main(){int j,n;float M;Good *goods; //=======/定义一个指针while(j){cout<<"=================================================="<<endl;cout<<"<09软件工程(1)班>----孙磊20090307139"<<endl;cout<<"=================================================="<<endl;cout<<endl;cout<<"\t"<<"请输入物品的总种类数:";cin>>n;goods=new struct Good [n+1];cout<<"\t"<<"请输入背包的最大容量:";cin>>M;cout<<endl;int i;for(i=1;i<=n;i++){ goods[i].flag=i;cout<<"\t"<<"请输入第"<<i<<"件物品的重量:";cin>>goods[i].w;cout<<"\t"<<"请输入第"<<i<<"件物品的效益:";cin>>goods[i].p;goods[i].p=goods[i].p/goods[i].w; //==========得出物品的效益,重量比cout<<endl;}Insertionsort(goods,n);bag(goods,M,n);cout<<"press [1] to run agian"<<endl;cout<<"press [0] to exit"<<endl;cin>>j;}}2.棋盘覆盖:#include<iostream>#include<stdlib.h>using namespace std;int tile=1;int board[100][100];void chessBoard(int tr, int tc, int dr, int dc, int size){if(size==1) return;int t=tile++;int s=size/2; //t为L型骨牌号,S分割棋盘if(dr<tr+s && dc<tc+s) //残缺方格位于左上棋盘chessBoard(tr, tc, dr, dc, s);else {board[tr+s-1][tc+s-1]=t; //覆盖1号三格板chessBoard(tr, tc, tr+s-1, tc+s-1, s); //覆盖其余部分}if(dr<tr+s && dc>=tc+s) //残缺棋盘位于右上棋盘chessBoard(tr, tc+s, dr, dc, s);else{board[tr+s-1][tc+s]=t; //覆盖2号三格板chessBoard(tr, tc+s, tr+s-1, tc+s, s); //覆盖其余部分}if(dr>=tr+s && dc<tc+s) //残缺方格位于左下棋盘chessBoard(tr+s, tc, dr, dc, s);else{board[tr+s][tc+s-1]=t; //覆盖3号三格板chessBoard(tr+s, tc, tr+s, tc+s-1, s); //覆盖其余部分}if(dr>=tr+s && dc>=tc+s) //残缺方格位于右下棋盘chessBoard(tr+s, tc+s, dr, dc, s);else{board[tr+s][tc+s]=t; //覆盖4号三格板chessBoard(tr+s, tc+s, tr+s, tc+s, s);//覆盖其余棋盘}}//===========主函数main()入口:==============void main(){ cout<<"=================================================="<<endl;cout<<"<09软件工程(1)班>----孙磊20090307139"<<endl;cout<<"=================================================="<<endl;cout<<endl;int size;cout<<"输入棋盘的size(大小必须是2的n次幂): "<<endl;cin>>size;int index_x,index_y;cout<<"输入特殊方格位置的坐标: "<<endl;cin>>index_x>>index_y;chessBoard(0,0,index_x,index_y,size);for(int i=0;i<size;i++){for(int j=0;j<size;j++)cout<<board[i][j]<<"\t";cout<<endl;}}六、测试分析1.普通背包给定数据如下:背包容量为M=150物品 A B C D E F G重量35 30 60 50 40 10 20效益10 40 30 50 35 40 30 1.1程序运行结果如下:1.2程序运行,输入物品总种类数:“7”,容量为:“150”;1.3依次输入物品的重量和物品的效益;1.4输完后,键入回车键,得出最佳解;2.棋盘覆盖:2.1程序运行结果如下:2.2按要求键入相应的值:2.3得出相应的解:2.3下图为键入其他值的解:算法分析:因为要覆盖(size^2-1)/3个三格板,所以算法的时间复杂度为O(size^2).七、结论普通背包问题采用贪心算法实现的,编程用C++语言。