回溯与分支限界算法设计.docx

上传人:b****5 文档编号:7826095 上传时间:2023-01-26 格式:DOCX 页数:16 大小:33.12KB
下载 相关 举报
回溯与分支限界算法设计.docx_第1页
第1页 / 共16页
回溯与分支限界算法设计.docx_第2页
第2页 / 共16页
回溯与分支限界算法设计.docx_第3页
第3页 / 共16页
回溯与分支限界算法设计.docx_第4页
第4页 / 共16页
回溯与分支限界算法设计.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

回溯与分支限界算法设计.docx

《回溯与分支限界算法设计.docx》由会员分享,可在线阅读,更多相关《回溯与分支限界算法设计.docx(16页珍藏版)》请在冰豆网上搜索。

回溯与分支限界算法设计.docx

回溯与分支限界算法设计

算法设计与分析实验报告

专业

班级

姓名

学号

实验名称

实验四:

回溯与分支限界算法设计

实验目的

1.掌握回溯法解决问题的一般步骤。

2.学会使用回溯法解决实际问题。

3.掌握分支限界法解决问题的基本思想。

4.学会使用分支限界法解决实际问题。

实验内容

1.骑士游历问题(采用回溯法):

在国际象棋的棋盘(8行×8列)上放置一个马,按照“马走日字”的规则,马要遍历棋盘,即到达棋盘上的每一格,并且每格只到达一次。

若给定起始位置(x0,y0),编程探索出一条路径,沿着这条路径马能遍历棋盘上的所有单元格。

2.行列变换问题(采用分支限界法):

给定两个mn方格阵列组成的图形A和图形B,每个方格的颜色为黑色或白色,如下图所示。

行列变换问题的每一步变换可以交换任意2行或2列方格的颜色,或者将某行或某列颠倒。

上述每次变换算作一步。

试设计一个算法,计算最少需要多少步,才能将图形A变换为图形B。

算法描述

1.骑士游历问题的解题思路或算法思想:

如果在每步选择方向时,不是任意选择一个方向,而是经过一定的测试和计算,“预见”每条路的“宽窄”,再选择一条最“窄”的路先走,成功的可能性较大。

理由是先走“困难的路”,光明大道留在后面。

因为每一格迟早都要走到,与其把困难留在后面,不如先走“困难的路”,这样路就会越走越宽,成功的机会就越大。

这种方法称为预见算法。

为每个方向测定一个值――可通路数,它表示该位置上还有多少条通路。

在每一格上对8个方向都进行试探,并分析比较,下一步应该选择可通路数值最小的方向走。

2.行列变换问题的解题思路或算法思想:

先进先出队列式分支限界法

输入数据,将计算出的最少变换次数和相应的变换序列输出。

第1行是最少变换次数。

从第2行开始,每行用4个数表示一次变换。

程序及运行结果

1.骑士游历问题的程序:

packagecom.t5;

importjava.util.Scanner;

publicclassQishi{

privatebooleanTravel(intfirstX,intfirstY,int[][]board){

//对应骑士可走的8个方向

int[]movex={-2,-1,1,2,2,1,-1,-2};

int[]movey={1,2,2,1,-1,-2,-2,-1};

//下一步出路的位置

int[]nextStepX=newint[board.length];

int[]nextStepY=newint[board.length];

//记录出路的个数

int[]exitS=newint[board.length];

intnextX=firstX;

intnextY=firstY;

board[nextX][nextY]=1;

for(intm=2;m<=Math.pow(board.length,2);m++){

//初始化下一个位置可走的位置的数目

for(inti=0;i

exitS[i]=0;

}

intcount=0;

//试探8个方向

for(inti=0;i<8;i++){

inttemI=nextX+movex[i];

inttemJ=nextY+movey[i];

//走到边界,路断

if(temI<0||temI>7||temJ<0||temJ>7){

continue;

}

//记录下可走的方向

if(0==board[temI][temJ]){

nextStepX[count]=temI;

nextStepY[count]=temJ;

count++;

}

}

//到这里,cout表示当前点有几种走法。

nextStep中存储各种走法的坐标。

intmin=-1;

if(count==0){

returnfalse;

}

if(1==count){

min=0;

}else{

for(inti=0;i

for(intj=0;j<8;j++)

{

inttemI=nextStepX[i]+movex[j];

inttemJ=nextStepY[i]+movey[j];

if(temI<0||temI>7||temJ<0||temJ>7){

continue;

}

//记录下这个位置可走的方向数

if(0==board[temI][temJ]){

exitS[i]++;

}

}

}

inttem=exitS[0];

min=0;

//从可走的方向中,寻找最少走的出路

for(inti=1;i

if(tem>exitS[i]){

tem=exitS[i];

min=i;

}

}

}

//得到最少的出路

nextX=nextStepX[min];

nextY=nextStepY[min];

board[nextX][nextY]=m;

}

returntrue;

}

publicstaticvoidmain(String[]args){

intfirstX,firstY;

System.out.println("输入起始点(0-7):

");

Scannerscanner=newScanner(System.in);

firstX=scanner.nextInt();

firstY=scanner.nextInt();

int[][]board=newint[8][8];

Qishiknight=newQishi();

if(knight.Travel(firstX,firstY,board)){

System.out.println("游历完成:

");

}else{

System.out.println("游历失败!

\n");

}

for(inti=0;i

for(intj=0;j

if(board[i][j]<10){

System.out.print(""+board[i][j]);

}else{

System.out.print(board[i][j]);

}

System.out.print("");

}

System.out.println();

}

}

}

实例:

2.行列变换问题的程序:

packagecom.t8;

importjava.util.LinkedList;

importjava.util.Scanner;

classgraph{

staticintsour,dest;//sour是图形的初始整数,dest是图形的目的整数

staticintans[]=newint[1<<16];//静态变量(即全局变量),用于存放图形变换的路径

intm=4,n=4,x;

introw[]=newint[4];

intcol[]=newint[4];

voidsetx(intx){

this.x=x;

}

intgetx(){

returnthis.x;

}

voidrowx(){//将一个整数划分成四行二进制

inty;

for(inti=0;i

y=1;

row[i]=0;

for(intj=0;j

if((x&1)!

=0)//如果x的最低位是1

row[i]|=y;

y<<=1;

x>>=1;

}

}

}

voidcolx(){//将一个整数划分成四列二进制

inty;

for(intj=0;j

y=1;

for(inti=0;i

for(intj=0;j

if((x&1)!

=0)//如果x的最低位是1

col[j]|=y;

x>>=1;

}

y<<=1;

}

}

voidrowy(){//将四行二进制转换成一个整数

intz=1,x=0,y;

for(inti=0;i

y=row[i];

for(intj=0;j

if((y&1)!

=0)//如果y的最低位是1

x|=z;

z<<=1;

y>>=1;

}

}

this.x=x;

}

voidcoly(){//将四列二进制转换成一个整数

intz=1,x=0,y;

for(inti=0;i

for(intj=0;j

if((col[j]&1)!

=0)//如果y的最低位是1

x|=z;

z<<=1;

col[j]>>=1;

}

}

this.x=x;

}

voidSwaprow(inti,intj){//将二进数进行行互换

into;

o=row[i];

row[i]=row[j];

row[j]=o;

}

voidSwapcol(inti,intj){//将二进数进行列互换

into;

o=col[i];

col[i]=col[j];

col[j]=o;

}

voidreveR(intk){//将二进数进行行颠倒

inty=0,z=1<<(4-1);

for(intj=0;j<4;j++){

if((row[k]&1)!

=0)//如果y的最低位是1

y|=z;

z>>=1;

row[k]>>=1;

}

row[k]=y;

}

voidreveC(intk){//将二进数进行列颠倒

inty=0,z=1<<(4-1);

for(intj=0;j<4;j++){

if((col[k]&1)!

=0)//如果y的最低位是1

y|=z;

z>>=1;

col[k]>>=1;

}

col[k]=y;

}

introwswap(intx,inti,intj){//将二进制数的第i行与第j行互换

this.x=x;

rowx();

Swaprow(i,j);

rowy();

returnthis.x;

}

intcolswap(intx,inti,intj){//将二进制数的第i列与第j列互换

this.x=x;

colx();

Swapcol(i,j);

coly();

returnthis.x;

}

intrevrow(intx,intk){//将二进制数的第K行颠倒

this.x=x;

rowx();

reveR(k);

rowy();

returnthis.x;

}

intrevcol(intx,intk){//将二进制数的第K列颠倒

this.x=x;

colx();

reveC(k);

coly();

returnthis.x;

}

}

publicclassTuxing{

publicstaticvoidmain(String[]args){

finalintMaxsize=1<<16;

graphgN;//用于进行行变换、列变换、行颠倒、列颠倒

intE,N;//变换前的初始值,变换前的结果值

gN=newgraph();

inthash[]=newint[1<<16];

inti,j,h=0;charc;

graphG1=newgraph();

//初始化,输入初始值和目标值,即1010010000101010和1010000001100101

Scannerscanner=newScanner(System.in);

Stringss=scanner.nextLine();

char[]chArrs=ss.toCharArray();

for(graph.sour=i=0;i<16;i++){

c=chArrs[i];

graph.sour|=(int)(c-'0')<

}

Stringsd=scanner.nextLine();

char[]chArrd=sd.toCharArray();

for(graph.dest=i=0;i<16;i++){

c=chArrd[i];

graph.dest|=(int)(c-'0')<

}

LinkedListqueue=newLinkedList();//初始化先进先出队列

for(intk=0;k

G1.x=graph.sour;

hash[G1.x]=0;

queue.add(G1.x);

while(!

queue.isEmpty()){//以先进先出队列式实现分支限界法

E=(int)queue.removeFirst();

for(i=0;i<4-1;i++){//行变换

for(j=i+1;j<4;j++){

gN.x=gN.rowswap(E,i,j);

N=gN.x;

if(hash[N]==-1){

hash[N]=hash[E]+1;

graph.ans[N]=E;

queue.add(N);

}

}

}

for(i=0;i<4-1;i++){//列变换

for(j=i+1;j<4;j++){

gN.x=gN.colswap(E,i,j);

N=gN.x;

if(hash[N]==-1){

hash[N]=hash[E]+1;

graph.ans[N]=E;

queue.add(N);

}

}

}

for(i=0;i<4;i++){//行颠倒

gN.x=gN.revrow(E,i);

N=gN.x;

if(hash[N]==-1){

hash[N]=hash[E]+1;

graph.ans[N]=E;

queue.add(N);

}

}

for(i=0;i<4;i++){//列颠倒

gN.x=gN.revcol(E,i);

N=gN.x;

if(hash[N]==-1){

hash[N]=hash[E]+1;

graph.ans[N]=E;

queue.add(N);

}

}

if(hash[graph.dest]!

=-1){//如果目的值被遍历到,则退出循环

System.out.println("OK");break;

}

}

System.out.println(hash[graph.dest]);

output(graph.dest);//输出变换的路径

}

publicstaticvoidoutb(intx){//将一个整数以四行二进制的形式显示

for(inti=0;i<4;i++){

for(intj=0;j<4;j++){

if((x&1)!

=0)System.out.print

(1);

elseSystem.out.print(0);

x/=2;

}

System.out.println();

}

}

publicstaticvoidoutput(intN){

if(N==graph.sour){

System.out.println();

outb(N);

return;

}

output(graph.ans[N]);//graph.ans[N]存放着从初始值到目的值的遍历路径

System.out.println();

outb(N);

}

}

实例:

总结

实验心得体会:

掌握回溯法解决问题的一般步骤。

学会使用回溯法解决实际问题。

掌握分支限界法解决问题的基本思想。

学会使用分支限界法解决实际问题

改进意见:

对于分支限界法了解的不透彻,应与老师沟通解决此问题,回溯法可以帮我们更好的解决一些多解的复杂性问题,所以,要更好的去学习和运用回溯法思想。

实验成绩:

指导教师:

年月日

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1