思路:題意很直觀,用密碼、光標位置來表示二維狀態,對光標所在位置分別進行六種操作,得到新狀態入隊。但一共有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;
}