思路:题意很直观,用密码、光标位置来表示二维状态,对光标所在位置分别进行六种操作,得到新状态入队。但一共有1000000*6种状态,所以需要剪枝。
由于swap0和swap1这两个交换操作只对光标处和0, 5位置的数字有效,当光标在j处时(0<j<5),若与目标状态的j位不一样,则使用left和right会失去修改第j位的机会(光标已不在此处,既不能swap也不能直接修改),只有当光标再次回到j时,才可向目标状态修改。故这种情况下使用left和right不是最优的。只有当前状态的j位与目标状态的j位相同时,才能使用left和right。
代码如下:
#include <cstdio> #include <queue> #include <cstring> using namespace std; #define N 1000005 #define M 7 #define UP 1 #define DOWN -1 char a[M], b[M]; int factor[M], num[6]; bool vis[N][6]; struct Node{ int val, idx, step; Node(int v, int i, int s): val(v), idx(i), step(s) {} }; int get_hash(char s[M]){ int res = 0; for(int i = 0; i < 6; ++i) res = s[i] - '0' + res * 10; return res; } inline int swap(int num, int idx1, int idx2){ int v1 = (num / factor[idx1]) % 10; int v2 = (num / factor[idx2]) % 10; num += (v2 - v1) * factor[idx1]; num += (v1 - v2) * factor[idx2]; return num; } inline int up_down(int num, int idx, int ops){ return num + ops * factor[idx]; } int bfs(int orig, int dest){ memset(vis, false, sizeof(vis)); queue<Node> qu; qu.push(Node(orig, 0, 0)); vis[orig][0] = true; while(!qu.empty()){ Node cur = qu.front(); qu.pop(); int sta = cur.val, idx = cur.idx, step = cur.step; if(sta == dest) return step; ++step; if(idx != 0){ //swap0 int next = swap(sta, 0, idx); if(!vis[next][idx]) qu.push(Node(next, idx, step)), vis[next][idx] = true; } if(idx != 5){ //swap1 int next = swap(sta, 5, idx); if(!vis[next][idx]) qu.push(Node(next, idx, step)), vis[next][idx] = true; } int val = (sta / factor[idx]) % 10; if(val != 9 && val != num[idx]){ //up int next = up_down(sta, idx, UP); if(!vis[next][idx]) qu.push(Node(next, idx, step)), vis[next][idx] = true; } if(val != 0 && val != num[idx]){ //down int next = up_down(sta, idx, DOWN); if(!vis[next][idx]) qu.push(Node(next, idx, step)), vis[next][idx] = true; } if(idx != 0 && (idx == 5 || val == num[idx])){ //left if(!vis[sta][idx - 1]) qu.push(Node(sta, idx - 1, step)), vis[sta][idx - 1] = true; } if(idx != 5 && (idx == 0 || val == num[idx])){ //right if(!vis[sta][idx + 1]) qu.push(Node(sta, idx + 1, step)), vis[sta][idx + 1] = true; } } return -1; } int main(){ factor[5] = 1; for(int i = 4; i >= 0; --i) factor[i] = 10 * factor[i + 1]; scanf("%s %s", a, b); for(int i = 0; i < 6; ++i) num[i] = b[i] - '0'; int orig = get_hash(a), dest = get_hash(b); printf("%d\n", bfs(orig, dest)); return 0; }