算法实验报告.docx
《算法实验报告.docx》由会员分享,可在线阅读,更多相关《算法实验报告.docx(25页珍藏版)》请在冰豆网上搜索。
算法实验报告
中南大学
算法设计与分析
实验报告
学生姓名惠苗壮
指导教师郑瑾
学院信息科学与工程学院
专业班级计科0904班
学号0909091627
完成时间2011年12月18日
目录
一.实验目的………………………………………1
二.实验要求………………………………………1
三.实验内容………………………………………1
四.实验分析………………………………………1
五.实验结果………………………………………15
六.实验心得………………………………………20
一.实验目的:
1.掌握动态规划、回溯法、分支限定法的原理。
2.能独立完成上述算法的实现。
3.能用上述算法解决问题。
二.实验要求:
1.给出相应的测试结果。
2.给出源代码及相应的注释。
3.所有的输入和输出都用文件处理。
三.实验内容:
1.实现求n皇后问题和子集和数问题的回溯算法。
2.用动态规划的方法实现0/1背包问题。
3.用分支限界法实现0/1背包问题。
4.用深度优化的方法遍历一个图,并判断图中是否有回路存在,如果有,请输出回路。
四.实验分析:
实验一:
实现求n皇后问题和子集和数问题的回溯算法。
问题说明:
按照国际象棋的规则在N*N的棋盘上放置彼此不受攻击的皇后问题。
数据表示:
用n个数彼此用“,”隔开来表示那个皇后的最后位置,如:
4皇后问题中,最后结果为1,3,0,2,表示第0列的皇后的位置在1,第1列的皇后的位置在3,第2列皇后的位置在0,第4列的皇后的位置在2.n皇后以此类推。
代码如下:
#include"stdio.h"
#include"stdlib.h"
#include"math.h"
intx[4]={0};
intPlace(intk)//判断第k行当前列是否可以放置皇后
{
for(inti=0;i{if(x[i]==x[k]||(abs(x[i]-x[k])-abs(i-k))==0){return0;}}return1;}voidNQueens(intk){x[k]=-1;while(1){x[k]=x[k]+1;while((x[k]<4)&&(!Place(k)))x[k]=x[k]+1;if(x[k]<4){if(k<3)NQueens(k+1);else{for(inti=0;i<4;i++){printf("%d,",x[i]);}printf("\n");}}elsereturn;}}intmain(intargc,char*argv[]){NQueens(0);system("PAUSE");}实验二:用动态规划的方法实现0/1背包问题。问题说明:给定n种物品和一背包。物品i的重量是w,其价值是v,背包的容量为C。求应怎样装入物体使得装入背包中的物体总价值最大。算法说明:采用动态规划的方法,将待求解问题分解成若干个子问题,然后从这些子问题的解得到原问题的解。在该问题中需要决定x1..xn的值。假设按i=1,2,...,n的次序来确定xi的值。如果置x1=0,则问题转变为相对于其余物品(即物品2,3,.,n),背包容量仍为c的背包问题。若置x1=1,问题就变为关于最大背包容量为c-w1的问题。现设r?{c,c-w1}为剩余的背包容量。 在第一次决策之后,剩下的问题便是考虑背包容量为r时的决策。不管x1是0或是1,[x2,.,xn]必须是第一次决策之后的一个最优方案,如果不是,则会有一个更好的方案[y2,.,yn],因而[x1,y2,.,yn]是一个更好的方案。 假设n=3,w=[100,14,10],p=[20,18,15],c=116。若设x1=1,则在本次决策之后,可用的背包容量为r=116-100=16。[x2,x3]=[0,1]符合容量限制的条件,所得值为15,但因为[x2,x3]=[1,0]同样符合容量条件且所得值为18,因此[x2,x3]=[0,1]并非最优策略。即x=[1,0,1]可改进为x=[1,1,0]。若设x1=0,则对于剩下的两种物品而言,容量限制条件为116。总之,如果子问题的结果[x2,x3]不是剩余情况下的一个最优解,则[x1,x2,x3]也不会是总体的最优解。在此问题中,最优决策序列由最优决策子序列组成。假设f(i,y)表示剩余容量为y,剩余物品为i,i+1,...,n时的最优解的值,即:利用最优序列由最优子序列构成的结论,可得到f的递归式为: 当j>=wi时: f(i,j)=max{f(i+1,j),f(i+1,j-wi)+vi}①式 当0<=j时: fn(1,c)是初始时背包问题的最优解。 以本题为例:若0≤y<10,则f(3,y)=0;若y≥10,f(3,y)=15。利用②式,可得f(2,y)=0(0≤y<10);f(2,y)=15(10≤y<14);f(2,y)=18(14≤y<24)和f(2,y)=33(y≥24)。因此最优解f(1,116)=max{f(2,116),f(2,116-w1)+p1}=max{f(2,116),f(2,16)+20}=max{33,38}=38。现在计算xi值,步骤如下:若f(1,c)=f(2,c),则x1=0,否则x1=1。接下来需从剩余容量c-w1中寻求最优解,用f(2,c-w1)表示最优解。依此类推,可得到所有的xi(i=1.n)值。 在该例中,可得出f(2,116)=33≠f(1,116),所以x1=1。接着利用返回值38-p1=18计算x2及x3,此时r=116-w1=16,又由f(2,16)=18,得f(3,16)=14≠f(2,16),因此x2=1,此时r=16-w2=2,所以f(3,2)=0,即得x3=0代码如下;#include#include#include"math.h"usingnamespacestd;intw[5]={2,2,6,5,4};intv[5]={6,3,5,4,6};intlength=5;intc=10;intm[5][10];voidknapsack(int*v,int*w,intc,intm[][10]){intn=length-1;intjMax=min(w[n]-1,c);for(intj=0;j<=jMax;j++){m[n][j]=0;}for(intj=w[n];j<=c;j++){m[n][j]=v[n];}for(inti=n-1;i>1;i--){jMax=min(w[i]-1,c);for(intj=0;j<=jMax;j++)//背包容量没有i物品大,则从i-n选物品装入包的中价值等于从i+1~nm[i][j]=m[i+1][j];for(intj=w[i];j<=c;j++)m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]);//包可以装入i,则分两种情况,一种是装i,一种是不装i,从中选最大}m[1][c]=m[2][c];if(c>=w[1])m[1][c]=max(m[1][c],m[1][c-w[1]]+v[1]);}voidtraceback(intm[][10],int*w,intc,int*x){intn=length-1;for(inti=0;i{if(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}}x[n]=(m[n][c]>0)?1:0;}intmain(intargc,char*argv[]){intx[5];knapsack(v,w,c,m);traceback(m,w,c,x);for(inti=0;i<5;i++){if(x[i]==1)printf("%d",w[i]);}//printf("%d",x[i]);system("PAUSE");returnEXIT_SUCCESS;}实验三:用分支限界法实现0/1背包问题。算法分析:采用分支限定法,对物品的选取与否构成一棵解树,左子树表示不装入,右表示装入,通过检索问题的解树得出最优解,并用结点上界杀死不符合要求的结点。代码如下:#include"stdlib.h"#include"math.h"#include"iostream"usingnamespacestd;//子集空间树结点classbbnode{friendclassKnap;friendintKnapsack(intp[],intw[],intc,intn,intbestx[]);private:bbnode*parent;//指向父结点的指针boolLChild;//左儿子结点标志};//对大堆结点classHeapNode{friendclassKnap;public:operatorint()const{returnuprofit;}intuprofit,//结点的价值上界profit;//结点所相应的价值intweight;//结点所相应的重量intlevel;//活结点在子集树种所处的层序号bbnode*ptr;//指向活结点在子集树种相应结点的指针};typedefstructHeap{intcapacity;intsize;HeapNode*Elem;}Heap,*MaxHeap;MaxHeapinitH(intmaxElem){MaxHeapH;H=(MaxHeap)malloc(sizeof(Heap));H->capacity=maxElem;H->Elem=(HeapNode*)malloc((maxElem)*sizeof(HeapNode));H->size=0;returnH;}voidInsertH(HeapNodex,MaxHeapH){inti,sindex=0;
if(x[i]==x[k]||(abs(x[i]-x[k])-abs(i-k))==0)
return0;
}
return1;
voidNQueens(intk)
x[k]=-1;
while
(1)
{x[k]=x[k]+1;
while((x[k]<4)&&(!
Place(k)))x[k]=x[k]+1;
if(x[k]<4)
{if(k<3)NQueens(k+1);
else
for(inti=0;i<4;i++)
printf("%d,",x[i]);
printf("\n");
elsereturn;
intmain(intargc,char*argv[])
NQueens(0);
system("PAUSE");
实验二:
用动态规划的方法实现0/1背包问题。
给定n种物品和一背包。
物品i的重量是w,其价值是v,背包的容量为C。
求应怎样装入物体使得装入背包中的物体总价值最大。
算法说明:
采用动态规划的方法,将待求解问题分解成若干个子问题,然后从这些子问题的解得到原问题的解。
在该问题中需要决定x1..xn的值。
假设按i=1,2,...,n的次序来确定xi的值。
如果置x1=0,则问题转变为相对于其余物品(即物品2,3,.,n),背包容量仍为c的背包问题。
若置x1=1,问题就变为关于最大背包容量为c-w1的问题。
现设r?
{c,c-w1}为剩余的背包容量。
在第一次决策之后,剩下的问题便是考虑背包容量为r时的决策。
不管x1是0或是1,[x2,.,xn]必须是第一次决策之后的一个最优方案,如果不是,则会有一个更好的方案[y2,.,yn],因而[x1,y2,.,yn]是一个更好的方案。
假设n=3,w=[100,14,10],p=[20,18,15],c=116。
若设x1=1,则在本次决策之后,可用的背包容量为r=116-100=16。
[x2,x3]=[0,1]符合容量限制的条件,所得值为15,但因为[x2,x3]=[1,0]同样符合容量条件且所得值为18,因此[x2,x3]=[0,1]并非最优策略。
即x=[1,0,1]可改进为x=[1,1,0]。
若设x1=0,则对于剩下的两种物品而言,容量限制条件为116。
总之,如果子问题的结果[x2,x3]不是剩余情况下的一个最优解,则[x1,x2,x3]也不会是总体的最优解。
在此问题中,最优决策序列由最优决策子序列组成。
假设f(i,y)表示剩余容量为y,剩余物品为i,i+1,...,n时的最优解的值,即:
利用最优序列由最优子序列构成的结论,可得到f的递归式为:
当j>=wi时:
f(i,j)=max{f(i+1,j),f(i+1,j-wi)+vi}①式
当0<=j时:
fn(1,c)是初始时背包问题的最优解。
以本题为例:
若0≤y<10,则f(3,y)=0;若y≥10,f(3,y)=15。
利用②式,可得f(2,y)=0(0≤y<10);f(2,y)=15(10≤y<14);f(2,y)=18(14≤y<24)和f(2,y)=33(y≥24)。
因此最优解f(1,116)=max{f(2,116),f(2,116-w1)+p1}=max{f(2,116),f(2,16)+20}=max{33,38}=38。
现在计算xi值,步骤如下:
若f(1,c)=f(2,c),则x1=0,否则x1=1。
接下来需从剩余容量c-w1中寻求最优解,用f(2,c-w1)表示最优解。
依此类推,可得到所有的xi(i=1.n)值。
在该例中,可得出f(2,116)=33≠f(1,116),所以x1=1。
接着利用返回值38-p1=18计算x2及x3,此时r=116-w1=16,又由f(2,16)=18,得f(3,16)=14≠f(2,16),因此x2=1,此时r=16-w2=2,所以f(3,2)=0,即得x3=0
代码如下;
#include
usingnamespacestd;
intw[5]={2,2,6,5,4};
intv[5]={6,3,5,4,6};
intlength=5;
intc=10;
intm[5][10];
voidknapsack(int*v,int*w,intc,intm[][10])
intn=length-1;
intjMax=min(w[n]-1,c);
for(intj=0;j<=jMax;j++)
m[n][j]=0;
for(intj=w[n];j<=c;j++)
m[n][j]=v[n];
for(inti=n-1;i>1;i--)
jMax=min(w[i]-1,c);
for(intj=0;j<=jMax;j++)//背包容量没有i物品大,则从i-n选物品装入包的中价值等于从i+1~n
m[i][j]=m[i+1][j];
for(intj=w[i];j<=c;j++)
m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]);//包可以装入i,则分两种情况,一种是装i,一种是不装i,从中选最大
m[1][c]=m[2][c];
if(c>=w[1])
m[1][c]=max(m[1][c],m[1][c-w[1]]+v[1]);
voidtraceback(intm[][10],int*w,intc,int*x)
for(inti=0;i{if(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}}x[n]=(m[n][c]>0)?1:0;}intmain(intargc,char*argv[]){intx[5];knapsack(v,w,c,m);traceback(m,w,c,x);for(inti=0;i<5;i++){if(x[i]==1)printf("%d",w[i]);}//printf("%d",x[i]);system("PAUSE");returnEXIT_SUCCESS;}实验三:用分支限界法实现0/1背包问题。算法分析:采用分支限定法,对物品的选取与否构成一棵解树,左子树表示不装入,右表示装入,通过检索问题的解树得出最优解,并用结点上界杀死不符合要求的结点。代码如下:#include"stdlib.h"#include"math.h"#include"iostream"usingnamespacestd;//子集空间树结点classbbnode{friendclassKnap;friendintKnapsack(intp[],intw[],intc,intn,intbestx[]);private:bbnode*parent;//指向父结点的指针boolLChild;//左儿子结点标志};//对大堆结点classHeapNode{friendclassKnap;public:operatorint()const{returnuprofit;}intuprofit,//结点的价值上界profit;//结点所相应的价值intweight;//结点所相应的重量intlevel;//活结点在子集树种所处的层序号bbnode*ptr;//指向活结点在子集树种相应结点的指针};typedefstructHeap{intcapacity;intsize;HeapNode*Elem;}Heap,*MaxHeap;MaxHeapinitH(intmaxElem){MaxHeapH;H=(MaxHeap)malloc(sizeof(Heap));H->capacity=maxElem;H->Elem=(HeapNode*)malloc((maxElem)*sizeof(HeapNode));H->size=0;returnH;}voidInsertH(HeapNodex,MaxHeapH){inti,sindex=0;
if(m[i][c]==m[i+1][c])
x[i]=0;
x[i]=1;
c-=w[i];
x[n]=(m[n][c]>0)?
1:
0;
intx[5];
knapsack(v,w,c,m);
traceback(m,w,c,x);
for(inti=0;i<5;i++)
if(x[i]==1)
printf("%d",w[i]);
//printf("%d",x[i]);
returnEXIT_SUCCESS;
实验三:
用分支限界法实现0/1背包问题。
算法分析:
采用分支限定法,对物品的选取与否构成一棵解树,左子树表示不装入,右表示装入,通过检索问题的解树得出最优解,并用结点上界杀死不符合要求的结点。
代码如下:
#include"iostream"
//子集空间树结点
classbbnode
friendclassKnap;
friendintKnapsack(intp[],intw[],intc,intn,intbestx[]);
private:
bbnode*parent;//指向父结点的指针
boolLChild;//左儿子结点标志
};
//对大堆结点
classHeapNode
public:
operatorint()const{returnuprofit;}
intuprofit,//结点的价值上界
profit;//结点所相应的价值
intweight;//结点所相应的重量
intlevel;//活结点在子集树种所处的层序号
bbnode*ptr;//指向活结点在子集树种相应结点的指针
typedefstructHeap
intcapacity;
intsize;
HeapNode*Elem;
}Heap,*MaxHeap;
MaxHeapinitH(intmaxElem)
MaxHeapH;
H=(MaxHeap)malloc(sizeof(Heap));
H->capacity=maxElem;
H->Elem=(HeapNode*)malloc((maxElem)*sizeof(HeapNode));
H->size=0;
returnH;
voidInsertH(HeapNodex,MaxHeapH)
inti,sindex=0;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1