【广搜】棋盘游戏
题目描述
在一个4*4的棋盘上有8个黑棋和8个白棋,当且仅当两个格子有公共边,这两个格子上的棋是相邻的。移动棋子的规则是交换相邻两个棋子。现在给出一个初始棋盘和一个最终棋盘,要求你找出一个最短的移动序列使初始棋盘变为最终棋盘。
Klux说:“这么简单的题目,我都会做!”
Klux说:“这么简单的题目,我都会做!”
输入
第1到4行每行四个数字(1或者0),描述了初始棋盘。
接着是一个空行。
第6到9行每行四个数字,描述了最终棋盘。
接着是一个空行。
第6到9行每行四个数字,描述了最终棋盘。
输出
第一行是一个整数n,表示最少的移动步数。
接下来n行每行4个数,r1,c1,r2,c2,表示移动的两个棋子的坐标(r1,c1),(r2,c2)(棋盘左上角的坐标为(1,1),并且他右边的格子为(1,2))
如果有许多组解,你可以输出任意一组。
接下来n行每行4个数,r1,c1,r2,c2,表示移动的两个棋子的坐标(r1,c1),(r2,c2)(棋盘左上角的坐标为(1,1),并且他右边的格子为(1,2))
如果有许多组解,你可以输出任意一组。
样例输入
1111
0000
1110
0010
1010
0101
1010
0101
样例输出
4
1 2 2 2
1 4 2 4
3 2 4 2
4 3 4 4
【题意】
交换即可,但是大家要这个状态不好标记处理,所以我们需要hash处理,这个01矩阵,不难想到我们处理成二进制来处理。
我们怎么处理这个题目中1,0对应的位置呢???我们可以用我们二维数组通用的hash方法,就是除以列宽得行号,对列宽取余得到列号的做法。
”交换“:如何实现??
同样地得到上下两个坐标的位置,同时其实他们对应的二进制也是序号来记录的,然后我们直接找到两个位置,用异或处理就可以交换0和1的操作。
怎么打印这个答案呢??
我认为这个题目还有一点就是记录路径的方法,记录路径是非常考验人的,但是我们需要开一个结构体,
这个结构体需要记录这次hash值对应的哪两个坐标进行交换了,同时这个结构体能通过最终状态的hash值回溯输出。
【代码】:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = (1<<16)+10; 4 int pre[N],vis[N]; 5 typedef struct Node { 6 int x,y,px,py ; 7 int pre_Num ; 8 }Node ; 9 Node ans[N]; 10 int n,m; 11 void dfs(int No){ 12 if( ans[No].pre_Num != n ) 13 dfs(ans[No].pre_Num); 14 printf("%d %d %d %d\n",ans[No].x,ans[No].y,ans[No].px,ans[No].py); 15 } 16 void BFS(){ 17 queue < int > Q ; 18 Q.push ( n ); 19 while ( !Q.empty() ) { 20 int cur = Q.front(); 21 Q.pop(); 22 // 上下互换 23 for(int i=0;i<=11;i++){ 24 int u = ( cur & (1<<i) ) >> i ; 25 int v = ( cur & (1<<i+4) ) >> (i+4); 26 int tmp = ( 1<<(i+4) ) + (1<<i) ; 27 if ( u != v ){ 28 int next = cur ^ tmp ; 29 if( vis[next] == 0 ){ 30 ans[next].x = i / 4 + 1 ; 31 ans[next].px = ans[next].x + 1 ; 32 ans[next].y = ans[next].py = i % 4 + 1 ; 33 ans[next].pre_Num = cur ; 34 vis[next] = vis[cur] + 1 ; 35 Q.push(next); 36 if ( next == m ){ 37 printf("%d\n",vis[m]); 38 dfs(next); 39 return ; 40 } 41 } 42 } 43 } 44 // 左右互换 45 for(int i=0;i<=15;i++){ 46 if(i%4==3) continue ; 47 int u = ( cur & (1<<i) ) >> i ; 48 int v = ( cur & (1<<(i+1)) ) >> (i+1); 49 int tmp = ( 1<<(i+1) ) + (1<<i) ; 50 if ( u != v ){ 51 int next = cur ^ tmp ; 52 if( vis[next] == 0 ){ 53 ans[next].px = ans[next].x = i / 4 + 1 ; 54 ans[next].y = i % 4 + 1 ; 55 ans[next].py = i % 4 + 2 ; 56 ans[next].pre_Num = cur ; 57 vis[next] = vis[cur] + 1 ; 58 Q.push(next); 59 if ( next == m ){ 60 printf("%d\n",vis[m]); 61 dfs(next); 62 return ; 63 } 64 } 65 } 66 } 67 } 68 } 69 int main() 70 { 71 for(int i=0,x;i<16;i++){ 72 scanf("%1d",&x); 73 n += x * (1<<i); 74 } 75 for(int i=0,x;i<16;i++){ 76 scanf("%1d",&x); 77 m += x * (1<<i); 78 } 79 if ( n==m ){ 80 return 0*puts("0"); 81 }else{ 82 BFS(); 83 } 84 return 0; 85 } 86 87 /* 88 89 1111 90 0000 91 1110 92 0010 93 94 1010 95 0101 96 1010 97 0101 98 99 */