「CODEVS1004」四子连棋
题目描述 Description
在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局。
● ○ ● ○ ● ○ ● ● ○ ● ○ ○ ● ○
输入描述 Input Description
1 从文件中读入一个4*4的初始棋局,黑棋子用B表示,白棋子用W表示,空格地带用O表示。
输出描述 Output Description
用最少的步数移动到目标棋局的步数。
样例输入 Sample Input
BWBO
WBWB
BWBW
WBWO
样例输出 Sample Output
5
题解
这显然是一道搜索相关的题目,每次找到空白的格子,将其与四周的棋子进行交换
这类求最小步数的题目往往迭代深搜可以秒杀
如果使用广度搜索,由于总局面数达到4 * 10^7,我们需要对局面进行判重,剪除重复搜索的分枝
这就需要用到哈希表,将局面看做16位的三进制数,转换十进制后取模作为key
据说迭代深搜可以秒杀
本题代码不考虑哈希表冲突的情况,不过由于最少步数的情况较多,得到错解的可能性比较低
valid函数用于与空白格交换的格子的合法性
equal用于判断四个字符是否相等
check用于判断是否为最终局面
gethash用于计算局面的哈希值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
#include<map> #include<set> #include<cmath> #include<stack> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define pi acos(-1) #define inf 1000000000 #define ll long long #define mod 9875321 using namespace std; ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int head,tail=2,ans=-1; bool mp[10000005],last[1000005]; int xx[4]={0,0,1,-1},yy[4]={-1,1,0,0}; char a[5][5]; char q[1000005][5][5]; int step[1000005]; bool valid(int x,int y,int t) { if(x>4||y>4||x<1||y<1||a[x][y]=='O')return 0; if(a[x][y]=='B'&&t==0)return 0; if(a[x][y]=='W'&&t==1)return 0; return 1; } bool equal(char a,char b,char c,char d) { if(a!=b||b!=c||c!=d)return 0; return 1; } bool check(char a[5][5]) { for(int i=1;i<=4;i++) { if(equal(a[i][1],a[i][2],a[i][3],a[i][4]))return 1; if(equal(a[1][i],a[2][i],a[3][i],a[4][i]))return 1; } if(equal(a[1][1],a[2][2],a[3][3],a[4][4]))return 1; if(equal(a[1][4],a[2][3],a[3][2],a[4][1]))return 1; return 0; } int gethash(char a[5][5]) { int t=0,key=0; for(int i=1;i<=4;i++) for(int j=1;j<=4;j++) { if(a[i][j]=='O')t=0; if(a[i][j]=='W')t=1; if(a[i][j]=='B')t=2; key=(key*3+t)%mod; } return key; } void move(int x,int y) { for(int k=0;k<4;k++) { int tx=x+xx[k],ty=y+yy[k]; if(!valid(tx,ty,last[head]))continue; for(int i=1;i<=4;i++) for(int j=1;j<=4;j++) a[i][j]=q[head][i][j]; swap(a[x][y],a[tx][ty]); if(mp[gethash(a)])continue; mp[gethash(a)]=1; tail++; for(int i=1;i<=4;i++) for(int j=1;j<=4;j++) q[tail][i][j]=a[i][j]; step[tail]=step[head]+1; last[tail]=last[head]^1; if(check(a))ans=step[tail]; } } void bfs() { while(head!=tail) { for(int i=1;i<=4;i++) for(int j=1;j<=4;j++) if(q[head][i][j]=='O') move(i,j); if(ans!=-1)return; head++; } } int main() { for(int i=1;i<=4;i++) scanf("%s",a[i]+1); for(int i=1;i<=4;i++) for(int j=1;j<=4;j++) q[0][i][j]=q[1][i][j]=a[i][j]; last[0]=0;last[1]=1; bfs(); printf("%d",ans); return 0; } |
Subscribe