Codevs 四子连棋 (迭代加深搜索)
题目描述 Description
在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局。
● | ○ | ● | |
○ | ● | ○ | ● |
● | ○ | ● | ○ |
○ | ● | ○ |
输入描述 Input Description
从文件中读入一个4*4的初始棋局,黑棋子用B表示,白棋子用W表示,空格地带用O表示。
输出描述 Output Description
用最少的步数移动到目标棋局的步数。
样例输入 Sample Input
BWBO
WBWB
BWBW
WBWO
样例输出 Sample Output
5
思路:(迭代加深搜索是限制的搜索深度的深搜,可以用来求解大部分的广度优先搜索的题目,不过要确定好搜索的起点和终点)
首先介绍一下迭代加深搜索: 迭代加深搜索就是在DFS时给定一个深度上限,当搜索深度超过上限时就不再拓展。从1开始枚举深度上限如果能找到解,这个上限就是最优解,否则就加大上限继续搜索。
现在我们来看这道题:由于黑白两色需要轮流动棋,在搜索时还要记录上一手是哪个颜色的棋移动,判断时也要注意这一点,开始搜索时也要考虑黑先手和白先手两种情况所以DFS时需要存储的状态有:两个空格的坐标,上一手棋的颜色和当前的深度。然后只要想到棋的移动等于空格的移动这一点即可。
代码如下:
1 #include<iostream> 2 #include<cstring> 3 4 using namespace std; 5 int map[6][6];//棋盘 6 int ox1=0,oy1=0,ox2=0,oy2=0,dep; 7 bool flag=false; 8 int movex[5]={0,1,0,-1,0},movey[5]={0,0,1,0,-1}; 9 bool ava(int x,int y,int pre)//判断下一步棋是否可以走 10 { 11 if(map[x][y]!=pre&&x>=1&&x<=4&&y>=1&&y<=4) 12 return true; 13 return false; 14 } 15 bool win()//判断是否走出了输赢 16 { 17 for(int i=1;i<=4;i++)//水平和垂直方向 18 { 19 if(map[i][1]==map[i][2]&&map[i][2]==map[i][3]&&map[i][3]==map[i][4]) 20 return true; 21 if(map[1][i]==map[2][i]&&map[2][i]==map[3][i]&&map[3][i]==map[4][i]) 22 return true; 23 }//以下是两个斜对角线 24 if(map[1][1]==map[2][2]&&map[2][2]==map[3][3]&&map[3][3]==map[4][4]) 25 return true; 26 if(map[1][4]==map[2][3]&&map[2][3]==map[3][2]&&map[3][2]==map[4][1]) 27 return true; 28 29 return false; 30 } 31 32 void iddfs(int x,int y,int p,int q,int pre,int step)//pre为棋盘的棋子类型,step为搜索深度即所走的步数 33 { 34 int nx,ny,qx,qy; 35 if(win()) 36 { 37 flag=true; 38 return ; 39 } 40 else if(step>dep)//如果当前深度超过了限制的深度 就停止 41 return; 42 for(int i=1;i<=4;i++) 43 { 44 nx=x+movex[i];//分别向四个方向移动 45 ny=y+movey[i]; 46 qx=p+movex[i]; 47 qy=q+movey[i]; 48 49 if(ava(nx,ny,pre))//以其中一个空格为起点 50 { 51 swap(map[x][y],map[nx][ny]);//交换空格和所移动的棋子 52 iddfs(nx,ny,p,q,map[x][y],step+1); 53 swap(map[x][y],map[nx][ny]); 54 } 55 if(ava(qx,qy,pre))//以另一个空格为起点 56 { 57 swap(map[p][q],map[qx][qy]); 58 iddfs(x,y,qx,qy,map[p][q],step+1); 59 swap(map[p][q],map[qx][qy]); 60 } 61 } 62 63 } 64 65 int main() 66 { 67 char s; 68 for(int i=1;i<=4;i++)//对输入的棋盘进行处理 69 for(int j=1;j<=4;j++) 70 { 71 cin>>s; 72 if(s=='B') 73 map[i][j]=1; 74 else if(s=='W') 75 map[i][j]=2; 76 else 77 { 78 map[i][j]=3; 79 if(!ox1) 80 { 81 ox1=i; 82 oy1=j; 83 } 84 else 85 { 86 ox2=i; 87 oy2=j; 88 } 89 } 90 } 91 for(dep=0;;dep++)//dep为搜索的限制程度 92 { 93 iddfs(ox1,oy1,ox2,oy2,1,1); 94 iddfs(ox1,oy1,ox2,oy2,2,1); 95 if(flag) 96 { 97 cout<<dep<<endl; 98 break; 99 } 100 } 101 return 0; 102 }