棋盘移动问题

 

5*5的棋盘上有24个棋子,有一个空位,棋子都不相同,现在随意的移动空位,只知道棋盘的初始状态和终止状态,以及每一种移动方法的次数,例如上5次等,求是否存在这样一个序列,如果存在,输出该序列,否则输出0

该题目的剪枝条件为

1,横向移动步数之和与初始座标之和为目标座标,同理纵向移动步数

2,每个方向的移动步数小于等于该方向最大的步数

3,每次移动不能超过边界

算法为典型的回朔法

#ifndef MOVECHESS_H #define MOVECHESS_H #include <iostream> #include <memory.h> class MoveChess { public:MoveChess() { mx[0]=-1; mx[1]=1; mx[2]=0; mx[3]=0; my[0]=0; my[1]=0; my[2]=-1; my[3]=1; out[0]=’L’; out[1]=’R’; out[2]=’U’; out[3]=’D’; for(int i=0;i<5;i++) for(int j=0;j<5;j++) { std::cin>>chessA[i][j]; x1[chessA[i][j]]=j; y1[chessA[i][j]]=i; } for(int i=0;i<5;i++) for(int j=0;j<5;j++) { std::cin>>chessB[i][j]; x2[chessB[i][j]]=j; y2[chessB[i][j]]=i; } std::cin>>b[1]>>b[2]>>b[3]>>b[4]; b[0]=b[1]+b[2]+b[3]+b[4]; ans=new int[b[0]]; if((x1[0]-b[1]+b[2]==x2[0])&&(y1[0]+b[4]-b[3]==y2[0])) solve(0); else std::cout<<0<<std::endl; } void solve(int n) { if(n==b[0]) { bool tf=false; for(int i=0;i<5;i++) for(int j=0;j<5;j++) { if(chessA[i][j]!=chessB[i][j]) tf=true; } if(!tf) { for(int j=0;j<b[0];j++) { std::cout<<out[ans[j]]<<” “; } std::cout<<std::endl; system(“pause”); exit(0); } } else { for(int i=0;i<4;i++) { if((b[i+1]>0)&&(x1[0]+mx[i]>=0&&x1[0]+mx[i]<5)&&(y1[0]+my[i]>=0&&y1[0]+my[i]<5)) { chessA[y1[0]][x1[0]]=chessA[y1[0]+my[i]][x1[0]+mx[i]]; x1[chessA[y1[0]+my[i]][x1[0]+mx[i]]]=x1[0]; y1[chessA[y1[0]+my[i]][x1[0]+mx[i]]]=y1[0]; x1[0]+=mx[i]; y1[0]+=my[i]; chessA[y1[0]][x1[0]]=0; ans[n]=i; solve(n+1); x1[0]-=mx[i]; y1[0]-=my[i]; x1[chessA[y1[0]][x1[0]]]+=mx[i]; y1[chessA[y1[0]][x1[0]]]+=my[i]; chessA[y1[0]+my[i]][x1[0]+mx[i]]=chessA[y1[0]][x1[0]]; chessA[y1[0]][x1[0]]=0; } } } } private: char out[4]; int b[5];//每个方向的操作次数,0代表总次数,1,2,3,4分别为左右上下 int mx[4]; int my[4]; int chessA[5][5];//移动前的棋盘 int chessB[5][5];//移动后的棋盘 int x1[25]; int y1[25]; int x2[25]; int y2[25]; int *ans; }; #endif 

【博客整理】

 

点赞