codevs1004四子连棋

1004 四子连棋

 

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold
 
 
题目描述 Description

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

 
 

 

输入描述 Input Description
从文件中读入一个4*4的初始棋局,黑棋子用B表示,白棋子用W表示,空格地带用O表示。
输出描述 Output Description

用最少的步数移动到目标棋局的步数。

样例输入 Sample Input

BWBO
WBWB
BWBW
WBWO

样例输出 Sample Output

5

 
#include<iostream>
#include<cstdio>
#include<cstdio>

using namespace std;
int map[5][5],ans,flag;
int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
inline void dfs(int ch, int deep);

inline void swap(int &a,int &b)
{
    int t = a;
    a = b;
    b = t;
}

bool check()//判断是否符合条件 
{
    for (int k=1;k<=4;k++)
    {
        if (map[k][1]==map[k][2]&&map[k][2]==map[k][3]&&map[k][3]==map[k][4])return 1;
        if (map[1][k]==map[2][k]&&map[2][k]==map[3][k]&&map[3][k]==map[4][k])return 1;
    }
    if (map[1][1]==map[2][2]&&map[2][2]==map[3][3]&&map[3][3]==map[4][4])return 1;
    if (map[1][4]==map[2][3]&&map[2][3]==map[3][2]&&map[3][2]==map[4][1])return 1;
    return 0;
}

void move(int ch,int deep,int x,int y) //ch表示下一个颜色 
{
    for(int i=1;i<=4;i++)
    {
        int xx=x+dx[i],yy=y+dy[i];
        if(map[xx][yy]==ch&&xx>0&&xx<5&&yy>0&&yy<5)
        {
            swap(map[x][y],map[xx][yy]);
            dfs(ch,deep+1);
            swap(map[x][y],map[xx][yy]);
        }
    }
}

void dfs(int ch,int deep)
{
    int next=!ch;
    if(flag) return;
    if(ans==deep)
    {
        if(check()) flag=1;
        return;
    }
    for(int i=1;i<=4;i++)
      for(int j=1;j<=4;j++)
        if(map[i][j]==-1) move(next,deep,i,j);
}

int main()
{
    for(int i = 1; i <= 4; i++)
           for(int j = 1; j <= 4; j++)
           {
               char a;
               cin>>a;
               if(a == 'B') map[i][j] = 1;
               if(a == 'O') map[i][j] = -1;
           }
    for(ans = 1; flag == 0; ans++)
    {
        dfs(0, 0);
        if(flag) break;
        dfs(1, 0);
        if(flag) break;
    }
    printf("%d\n",ans);
}
dfs

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#define maxn 5001

using namespace std;
struct node
{
    int map[5][5];
    int f;//表示这一步走的棋子是黑还是白 
};node e[5000];
int mm[5][5],tep[maxn],head=0,tail=1,ans=maxn,flag;
int dx[5]={0,0,0,1,-1};
int dy[5]={0,1,-1,0,0};
map<string,bool> hash;

bool equ(int a1,int a2,int a3,int a4){if(a1!=a2||a2!=a3||a3!=a4||a4!=a1)return 0;return 1;}
bool judge(int w)
{
    for(int i=1;i<=4;i++)
    {
        if(equ(e[w].map[i][1],e[w].map[i][2],e[w].map[i][3],e[w].map[i][4]))return 1;
        if(equ(e[w].map[1][i],e[w].map[2][i],e[w].map[3][i],e[w].map[4][i]))return 1;
    }
    if(equ(e[w].map[1][1],e[w].map[2][2],e[w].map[3][3],e[w].map[4][4]))return 1;
    if(equ(e[w].map[1][4],e[w].map[2][3],e[w].map[3][2],e[w].map[4][1]))return 1;
    return 0;
}

void copy()
{
    for(int k=1;k<=4;k++)
      for(int l=1;l<=4;l++)
        e[tail].map[k][l]=e[head].map[k][l];
}

bool check(node x)//hash判重 
{
    string s="";
    for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
            s+=x.map[i][j]+'1';
    if(hash[s])return true;
    hash[s]=1;return false;
}

void Bfs()
{
    while(head<tail)
    {
        head++;
        for(int i=1;i<=4;i++)
          for(int j=1;j<=4;j++)
          {
              if(e[head].map[i][j]==0)
              {
                  for(int cnt=1;cnt<=4;cnt++)
                  {
                      int x=i+dx[cnt],y=j+dy[cnt];
                      if(x>0&&x<5&&y>0&&y<5&&e[head].map[x][y]!=e[head].f&&e[head].map[x][y]!=0)
                      {
                          ++tail;
                          copy();
                          e[tail].map[x][y]=0;
                          if(e[head].f==1)
                        {
                              e[tail].f=-1;
                              e[tail].map[i][j]=-1;
                        }
                          else
                        {
                            e[tail].f=1;
                            e[tail].map[i][j]=1;
                        }
                          tep[tail]=tep[head]+1;
                          if(judge(tail))
                          {
                              flag=1;
                              ans=min(ans,tep[tail]);
                              break;//手残打成return... 
                        }
                        if(check(e[tail])) tail--;
                    }
                }
            }
            if(flag)break;
          }
    }
}


int main()
{
    for(int i=1;i<=4;i++)
      for(int j=1;j<=4;j++)
      {
          char c;
          cin>>c;
          if(c=='W')mm[i][j]=1;
          else if(c=='B')mm[i][j]=-1;
          else mm[i][j]=0;
      }
    for(int k=1;k<maxn;k++)
      for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
        {
            e[1].map[i][j]=mm[i][j];
            e[k].f=0;
            tep[k]=0;
        }
    flag=0;ans=maxn;
    e[1].f=-1;
    Bfs();
    hash.clear();
    for(int k=1;k<maxn;k++)
      for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
        {
            e[1].map[i][j]=mm[i][j];
            e[k].f=0;
            tep[k]=0;
        }
    head=0;tail=1;flag=0;
    e[1].f=1;
    Bfs();//因为一开始走黑棋白棋结果可能不一样,所以两遍 
    printf("%d\n",ans);
    return 0;
}
bfs

 

posted @ 2017-02-18 15:26  安月冷  阅读(145)  评论(0编辑  收藏  举报