【广搜】棋盘游戏

题目描述

在一个4*4的棋盘上有8个黑棋和8个白棋,当且仅当两个格子有公共边,这两个格子上的棋是相邻的。移动棋子的规则是交换相邻两个棋子。现在给出一个初始棋盘和一个最终棋盘,要求你找出一个最短的移动序列使初始棋盘变为最终棋盘。
Klux说:“这么简单的题目,我都会做!”

输入

第1到4行每行四个数字(1或者0),描述了初始棋盘。
接着是一个空行。
第6到9行每行四个数字,描述了最终棋盘。

 

输出

第一行是一个整数n,表示最少的移动步数。
接下来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 */
棋盘游戏

 

posted @ 2019-07-19 21:09  Osea  阅读(464)  评论(0编辑  收藏  举报