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 }
时间: 2024-10-12 07:19:13

Codevs 四子连棋 (迭代加深搜索)的相关文章

codevs 2541 幂运算(迭代加深搜索)

/* 一开始想到了简单的深搜 维护当前可用的mi数组 然后回溯用哪个 不断更新新产生的mi 这样的问题是 由于mi不断产生 搜索规模扩大 不好 不好 下面是奇丑的WA掉的代码 做个反面教材 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,ans=0x3f3f3f3f,f[1055],s[1055],top,vis[1055]; void Dfs(int

迭代加深搜索[codevs1004 四子连棋]

迭代加深搜索 一.算法简介 迭代加深搜索是在速度上接近广度优先搜索,空间上和深度优先搜索相当的搜索方式.由于在使用过程中引入了深度优先搜索,所以也可以当作深度优先搜索的优化方案. 迭代加深搜索适用于当搜索深度没有明确上限的情况. 例如上图的一棵搜索树,在进行深度优先搜索前先规定好这次搜索的最大深度dep,当搜索到达dep却还没搜索到结果时回溯. 之后不断加大搜索深度,重新搜索,直到找到结果为止.虽然这样搜索次数会累计很多次,但每一次搜索的范围和下一次搜索的范围相比微不足道,所以整体搜索速度不会受

【日常学习】【迭代加深搜索+哈希】codevs1004 四子连棋题解

转载请注明出处 [ametake版权所有]http://blog.csdn.net/ametake 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局. ● ○ ●   ○ ● ○ ● ● ○ ● ○ ○ ● ○   输入描述 Input

【宽度优先搜索】神奇的状态压缩 CodeVs1004四子连棋

一.写在前面 其实这是一道大水题,而且还出在了数据最水的OJ上,所以实际上这题并没有什么难度.博主写这篇blog主要是想写下一个想法--状态压缩.状态压缩在记录.修改状态以及判重去重等方面有着极高的(←_←词穷了,诸位大致理解一下就好)效率.博主原本打算在blog介绍一种DP--状态压缩型动态规划,但动笔(键盘??)前,博主突然想起自己前些年写过的一道广搜题,当时在判重方面冥思苦想想出了一种类似状态压缩的方法,开心了好久,于是在此先抛砖引玉为状压DP做个铺垫. 二.题目 Description

迭代加深搜索 codevs 2541 幂运算

codevs 2541 幂运算 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 从m开始,我们只需要6次运算就可以计算出m31: m2=m×m,m4=m2×m2,m8=m4×m4,m16=m8×m8,m32=m16×m16,m31=m32÷m. 请你找出从m开始,计算mn的最少运算次数.在运算的每一步,都应该是m的正整数次方,换句话说,类似m-3是不允许出现的. 输入描述 Input Description 输入为一个正整

Codevs 1004 四子连棋

1004 四子连棋 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局. ● ○ ●   ○ ● ○ ● ● ○ ● ○ ○ ● ○   输入描述 Input

Codevs p1004 四子连棋

                      四子连棋 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局. ● ○ ●   ○ ● ○ ● ● ○ ● ○ ○ ● ○   输入描述 Input Description 从文件中读入一个4*4

codevs 1004 四子连棋 BFS、hash判重

004 四子连棋 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局. ● ○ ●   ○ ● ○ ● ● ○ ● ○ ○ ● ○   输入描述 Input

codevs1004四子连棋[BFS 哈希]

1004 四子连棋  时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局. ● ○ ●   ○ ● ○ ● ● ○ ● ○ ○ ● ○   输入描述 Inpu