《算法设计与分析》实验二09770106刘东辉Word文档下载推荐.docx
- 文档编号:16470454
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:22
- 大小:62.38KB
《算法设计与分析》实验二09770106刘东辉Word文档下载推荐.docx
《《算法设计与分析》实验二09770106刘东辉Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《《算法设计与分析》实验二09770106刘东辉Word文档下载推荐.docx(22页珍藏版)》请在冰豆网上搜索。
1.运用回溯算法求解0-1背包问题;
2.运用回溯算法求解4城市旅行商问题;
3.运用回溯算法求解N后问题。
【分支限界算法】
1.运用分支限界算法求解0-1背包问题;
2.运用分支限界算法求解4城市旅行商问题。
【其他搜索算法】
1.运用深度优先搜索算法求解马走棋盘问题;
2.运用A*算法求解九宫问题。
四、实验过程
1题目分析和算法构造
在此论证算法设计中的一些必要的设计依据。
将棋盘平分四部分,一直分,知道含有特殊方格,看特殊方格在那一部分中,在延边用L型骨牌覆盖。
2算法实现
程序源代码(请写入必要的注释)。
棋盘
#include<
iostream>
cmath>
usingnamespacestd;
/*****************************************************
*参数含义:
*tr--当前棋盘左上角的行号
*tc--当前棋盘左上角的列号
*dr--当前特殊方格所在的行号
*dc--当前特殊方格所在的列号
*****************************************************/
intBoard[100][100];
//用来存放棋盘元素的数组
inttile=1;
//L型骨牌的投放序号
voidChessBoard(inttr,inttc,intdr,intdc,intsize)
{
if(size==1){//棋盘方格大小为,说明递归到最里层
return;
}
intt=tile++;
//每次递增
ints=size/2;
//分割棋盘
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);
}
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&
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);
=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);
}
voidmain()
intn;
intsize;
//棋盘大小
cout<
<
"
请输入一个数字n,将为您创建的n次方大小的棋盘:
;
cin>
>
n;
intx,y;
size=(int)pow(2.0,(int)n);
cout<
"
输入特殊方格的横坐标:
cin>
x;
输入特殊方格的纵坐标:
y;
endl;
ChessBoard(0,0,x,y,size);
程序运行结果如下所示:
<
endl<
for(inti=0;
i<
size;
i++){
for(intj=0;
j<
j++){
Board[i][j]<
\t"
system("
pause"
);
3.运行结果
4经验归纳
棋盘覆盖的是基本思想基于分治策略,即是将棋盘平分四部分
1.题目分析和算法构造
N个数字来排队;
两两相比小靠前;
外层n-1;
内层n-i-1。
2.算法实现
冒泡
intmain(){
inta[10];
inti,b=0;
for(i=0;
10;
i++)
{cin>
a[i];
{for(intj=0;
9-i;
j++)
{if(a[j]>
a[j+1]){
b=a[j];
a[j]=a[j+1];
a[j+1]=b;
cout<
a[i]<
return0;
3.运行结果
4.经验归纳
冒泡排序的基本思想就是利用双重for循环。
1题目分析和算法构造
将一组数从中间分成两部分,左侧的都小于中间数,右侧的都大于中间数。
然后在两部分重复上述过程,直到完成排序。
快速排序
#include<
voidkuaisu(int*p,intleft,intright)
inti(left),j(right),middle(0),iTemp(0);
middle=p[(left+right)/2];
//求中间值
do{
while((p[i]<
middle)&
(i<
right))//从左扫描大于中值的数
i++;
while((p[j]>
middle)&
(j>
left))//从右扫描小于中值的数
j--;
//找到了一对值,交换
if(i<
=j)
{
iTemp=p[j];
p[j]=p[i];
p[i]=iTemp;
}while(i<
=j);
//如果两边扫描的下标交错,就停止(完成一次)
//当左边部分有值(left<
j),递归左半边
if(left<
j)
kuaisu(p,left,j);
//当右边部分有值(right>
i),递归右半边
if(right>
i)
kuaisu(p,i,right);
}
intmain()
{
intdata[]={10,9,8,7,6,5,4,3,2,1};
kuaisu(data,0,10);
{
data[i]<
endl;
递归左右部分。
分成若干小区间内进行排序,相邻区间两两合一,在进行排序,最后完成排序。
合并
#include<
#definen9
template<
classType>
voidMergeSort(Typea[],intleft,intright)
right)//保证至少有两个元素
Type*b=newType[right-left];
//临时存储数据
inti=(left+right)/2;
//取中点
MergeSort(a,left,i);
MergeSort(a,i+1,right);
Merge(a,b,left,i,right);
//合并到数组b
Copy(a,b,left,right);
//复制回数组a
voidCopy(Typea[],Typeb[],intleft,intright)
for(inti=left;
i<
=right;
i++)
a[i]=b[i];
voidMerge(Typec[],Typed[],intl,intm,intr)
inti=l;
intj=m+1;
intk=l;
while((i<
=m)&
(j<
=r))
if(c[i]<
=c[j])
{
d[k++]=c[i++];
}
else
d[k++]=c[j++];
if(i>
m)
for(intq=j;
q<
=r;
q++)
d[k++]=c[q];
else
for(intq=i;
=m;
intdata[n];
inti,j;
请依次输入数组的元素:
for(i=0;
data[i];
MergeSort(data,0,n-1);
//用递归实现的合并排序算法
for(j=0;
j++)//打印输出结果
data[j];
endl;
合并排序法的基本思想是基于分治策略
运用动态规划算法求解最大子段和问题
给出一段序列,找到这个序列的子序列的最大和。
用一维数组来存储这段序列,调用求子段和的动态规划算法。
#definem7
intmaxSubSum(int*a,intn)
intsum=a[n-1];
ints=a[n-1];
inti;
for(i=n-2;
i>
=0;
i--){
if(s<
0)
s=0;
s+=a[i];
if(s>
sum)//若当前子数组之和大于sum,则更新sum
sum=s;
returnsum;
voidmain()
intdata[m];
m;
intmaxSub=maxSubSum(data,m);
//递归
maxSub<
当前子数组之和大于sum,则更新sum
找零钱
希望用数目最少的硬币找零钱。
inta,b25,b10,b5,b2,b1;
请输入要找的零钱:
a;
b25=(a/25);
b10=(a%25)/10;
b5=(a%25)%10/5;
b2=(a%25)%10%5/2;
b1=(a%25)%10%5%2;
需要以下几枚零钱:
if(b25!
=0)
25分的"
b25<
枚"
if(b10!
10分的"
b10<
if(b5!
5分的"
b5<
if(b2!
2分的"
b2<
if(b1!
1分的"
b1<
贪心算法的基本思想:
从问题的一个初始解逼近给定的目标,以尽可能快的求得更好的解。
0—1背包
0-1背包问题的解空间可用子集树表示。
在搜索解空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左子树。
当右子树有可能包含最优解时才进入右子树搜索。
否则将右子树剪去。
设r是当前剩余物品价值总和;
cp是当前价值;
bestp是当前最优价值。
当cp+r≤bestp时,可剪去右子树。
计算右子树中解的上界的更好方法是将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包。
由此得到的价值是右子树中解的上界。
//类knap的数据成员记录解空间树的结点信息
classKnap
friendintKnapsack(intp[],intw[],intc,intn);
public:
voidprint()
for(intm=1;
m<
=n;
m++)
bestx[m]<
};
private:
intBound(inti);
voidBacktrack(inti);
intc;
//背包容量
intn;
//物品数
int*w;
//物品重量数组
int*p;
//物品价值数组
intcw;
//当前重量
intcp;
//当前价值
intbestp;
//当前最优值
int*bestx;
//当前最优解
int*x;
//当前解
intKnap:
:
Bound(inti)
//计算上界
intcleft=c-cw;
//剩余容量
intb=cp;
//以物品单位重量价值递减序装入物品
while(i<
=n&
w[i]<
=cleft)
cleft-=w[i];
b+=p[i];
//装满背包
if(i<
=n)
b+=p[i]/w[i]*cleft;
returnb;
//深度优先搜索整个解空间
voidKnap:
Backtrack(inti)
if(i>
n)
if(bestp<
cp)
for(intj=1;
j++)
bestx[j]=x[j];
bestp=cp;
return;
if(cw+w[i]<
=c)//搜索左子树
x[i]=1;
cw+=w[i];
cp+=p[i];
Backtrack(i+1);
cw-=w[i];
cp-=p[i];
if(Bound(i+1)>
bestp)//搜索右子树
x[i]=0;
classObject
friendintKnapsack(intp[],intw[],intc,intn);
intoperator<
=(Objecta)const
return(d>
=a.d);
intID;
floatd;
intKnapsack(intp[],intw[],intc,intn)
//为Knap:
Backtrack初始化
intW=0;
intP=0;
inti=1;
Object*Q=newObject[n];
for(i=1;
i++)
Q[i-1].ID=i;
Q[i-1].d=1.0*p[i]/w[i];
P+=p[i];
W+=w[i];
if(W<
=c)
returnP;
//装入所有物品
//依物品单位重量排序
floatf;
for(i=0;
for(intj=i;
if(Q[i].d<
Q[j].d)
f=Q[i].d;
Q[i].d=Q[j].d;
Q[j].d=f;
KnapK;
K.p=newint[n+1];
K.w=newint[n+1];
K.x=newint[n+1];
K.bestx=newint[n+1];
K.x[0]=0;
K.bestx[0]=0;
for(i=1;
K.p[i]=p[Q[i-1].ID];
K.w[i]=w[Q[i-1].ID];
K.cp=0;
K.cw=0;
K.c=c;
K.n=n;
K.bestp=0;
//回溯搜索
K.Backtrack
(1);
K.print();
delete[]Q;
delete[]K.w;
delete[]K.p;
returnK.bestp;
voidmain()
intc=0;
intn=0;
inti=0;
cout<
0-1背包问题-回溯法"
请输入背包容量(c):
cin>
c;
请输入物品的个数(n):
p=newint[n+1];
w=newint[n+1];
p[0]=0;
w[0]=0;
请输入物品的价值(p):
p[i];
请输入物品的重量(w):
w[i];
最优解为(bestx):
最优值为(bestp):
Knapsack(p,w,c,n)<
3运行结果
请仿照此步骤写实验过程。
五、实验总结
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法设计与分析 算法 设计 分析 实验 09770106 刘东辉
![提示](https://static.bdocx.com/images/bang_tan.gif)