柯南再破难关
柯南再破难关
题目描述:
OIBH组织派出的黄金十二人+青铜五小强还没有到, 他们只能指望原先的机关能够阻拦住柯南的脚步,柯南打开大门之后发现里面还有一个门, 门上还有一个神奇的锁(-,-),这是一个4*4的锁, 上面有8个凸起的格子和8个被按下的格子,当且仅当两个格子有公共边时, 则称这两个格子是相邻的。
每次操作只能够交换相邻的两个格,柯南看到了初始锁的状态和目标锁的状态,同样组织只允许他用最少步数打开锁。
输入格式:
第1到4行每行四个数字(1或者0),描述了初始锁状态
接着是一个空行
第6到9行每行四个数字,描述了最终锁状态
输出格式:
输出文件只有一行,是一个整数n,表示最少的操作次数。
样例输入:
1111 0000 1110 0010 1010 0101 1010 0101
样例输出:
4
提示:
本题是非常典型的广搜题,难点在于hash表的设计。
时间限制:1000ms
空间限制:128MByte
#include<bits/stdc++.h> using namespace std; struct node{ int a[5][5]; bool operator == (const node &b) const { for(int i = 1; i <= 4; i++) for(int j = 1; j <= 4; j++) if(a[i][j] != b.a[i][j]) return 0; return 1; } }; struct enode{ node a; int step; enode(node a1, int s1) : a(a1), step(s1) {} }; queue<enode> q; int b[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; bool p[65536]; bool pd(node x) { int sum = 0; for(int i = 1; i <= 4; i++) for(int j = 1; j <= 4; j++) sum += x.a[i][j] * pow(2, (i - 1) * 4 + (j - 1)); return p[sum]; } void se(node x) { int sum = 0; for(int i = 1; i <= 4; i++) for(int j = 1; j <= 4; j++) sum += x.a[i][j] * pow(2, (i - 1) * 4 + (j - 1)); p[sum] = 1; } int main() { char ch; node st, fin; for(int i = 1; i <= 4; i++) for(int j = 1; j <= 4; j++) cin>>ch, st.a[i][j] = ch - '0'; for(int i = 1; i <= 4; i++) for(int j = 1; j <= 4; j++) cin>>ch, fin.a[i][j] = ch - '0'; q.push(enode(st, 0)); se(st); while(!q.empty()){ int x1, y1; node n = q.front().a; int st = q.front().step; q.pop(); if(n == fin){ cout<<st<<endl; return 0; } for(int i = 1; i <= 4; i++) for(int j = 1; j <= 4; j++) for(int k = 0; k < 4; k++){ x1 = i + b[k][0], y1 = j + b[k][1]; if(x1 > 0 && x1 <= 4 && y1 > 0 && y1 <= 4){ swap(n.a[i][j], n.a[x1][y1]); if(!pd(n)){ se(n); q.push(enode(n, st +1)); } swap(n.a[i][j], n.a[x1][y1]); } } } return 0; }