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 }
原文地址:https://www.cnblogs.com/wangrunhu/p/7764304.html