zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    [luoguP3953] 逛公园(DP + spfa)
    [luoguP3960] 列队(动态开点线段树)
    [luoguP2325] [SCOI2005]王室联邦(树分块乱搞)
    [luoguP1053] 篝火晚会(贪心 + 乱搞)
    Linux_C socket 一些知识
    Linux_C socket 服务器(cat ,execl功能)
    Linux_C socket server.c clinet.c功能分开写
    Linux_C socket clinet.c
    Linux_C AF_INET和PF_INET的细微不同
    Linux_socket一些基本函数和结构体
  • 原文地址:https://www.cnblogs.com/wangrunhu/p/7764304.html
Copyright © 2011-2022 走看看