题目描述 Description
在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局。
● ○ ●
○ ● ○ ●
● ○ ● ○
○ ● ○
输入描述 Input Description
从文件中读入一个4*4的初始棋局,黑棋子用B表示,白棋子用W表示,空格地带用O表示。
输出描述 Output Description
用最少的步数移动到目标棋局的步数。
样例输入 Sample Input
BWBO
WBWB
BWBW
WBWO
样例输出 Sample Output
5
数据范围及提示 Data Size & Hint
hi
题解:
一道迭代加深的题目。。check的时候暴力check都行,不过也可以用hash?
其实也可以拿来练bfs,不过先坑着吧。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 5;
int n=4;
char s[N][N];
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
bool check(){
for(int i=0;i<4;++i){
bool flag=true;
for(int j=1;j<4;++j) if(s[i][j]!=s[i][0]) {flag=false;break;}
if(flag==true) return true;
}
for(int j=0;j<4;++j){
bool flag=true;
for(int i=1;i<4;++i) if(s[i][j]!=s[0][j]) {flag=false;break;}
if(flag==true) return true;
}
bool flag=true;
if(s[1][1]!=s[0][0]||s[2][2]!=s[0][0]||s[3][3]!=s[0][0]) flag=false;
if(flag==true) return true;
if(s[1][2]!=s[0][3]||s[2][1]!=s[0][3]||s[3][0]!=s[0][3]) flag=false;
if(flag==true) return true;
return false;
}
int dfs(int d,int limit,int ex1,int ey1,int ex2,int ey2,int color){
if(d>limit){
if(check()) return true;
return false;
}
for(int i=0;i<4;++i){
int x=ex1+dx[i],y=ey1+dy[i];
char c;if(color==1) c='B';else c='W';
if(x>=0&&x<4&&y>=0&&y<4&&s[x][y]==c){
swap(s[x][y],s[ex1][ey1]);
if(dfs(d+1,limit,x,y,ex2,ey2,color^1)) return true;
swap(s[x][y],s[ex1][ey1]);
}
x=ex2+dx[i],y=ey2+dy[i];
if(x>=0&&x<4&&y>=0&&y<4&&s[x][y]==c){
swap(s[x][y],s[ex2][ey2]);
if(dfs(d+1,limit,ex1,ey1,x,y,color^1)) return true;
swap(s[x][y],s[ex2][ey2]);
}
}
return false;
}
int main(){
for(int i=0;i<4;++i){
scanf("%s",s[i]);
}
int ans=0;
int ex1=-1,ex2=-1,ey1=-1,ey2=-1;
for(int i=0;i<4;++i){
for(int j=0;j<4;++j){
if(s[i][j]=='O'&&ex1==-1) ex1=i,ey1=j;
else if(s[i][j]=='O'&&ex2==-1) {ex2=i,ey2=j;break;}
}
if(ex2!=-1) break;
}
for(;;++ans){
if(dfs(1,ans,ex1,ey1,ex2,ey2,0)) break;
if(dfs(1,ans,ex1,ey1,ex2,ey2,1)) break;
}
printf("%d\n",ans);
return 0;
}