题目链接:Eight II
解析:还是八数码问题,当然还是A*了,只不过这次要加上预处理才行。
先枚举出‘X’的位置,然后用前驱表保存所有情况
然后直接回溯就行了,不用再搜了。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
#include <stack>
using namespace std;
struct Node{
char mz[3][3];
int x, y;
Node(){}
Node(char* str){
int xx = 0, yy = 0;
for(int i=0; str[i]; i++){
mz[xx][yy] = str[i];
if(str[i] == 'X'){
x = xx;
y = yy;
}
yy ++;
if(yy == 3){
xx ++;
yy = 0;
}
}
}
}start;
int fac[]= {1,1,2,6,24,120,720,5040,40320};
int num[11];
int dir[4][2] = {1, 0, 0, -1, 0, 1, -1, 0};
char to_s[5] = "dlru";
int _hash(Node &a){
char s[11];
int ans = 0;
for(int i=0; i<3; i++)
for(int j=0; j<3; j++){
s[i*3+j] = a.mz[i][j];
int cnt = 0;
for(int k=i*3+j-1; k>=0; k--)
if(s[k] > s[i*3+j]) cnt ++;
ans += fac[i*3+j]*cnt;
}
return ans;
}
char str[11], op[11][400000];
int pre[11][400000];
bool vis[400000];
void bfs(int x){
memset(vis, false, sizeof(vis));
memset(pre[x], -1, sizeof(pre[x]));
queue<Node> q;
q.push(start);
vis[_hash(start)] = true;
while(!q.empty()){
Node now = q.front(); q.pop();
int hnow = _hash(now);
for(int i=0; i<4; i++){
Node tp = now;
tp.x += dir[i][0];
tp.y += dir[i][1];
if(tp.x < 0 || tp.y < 0 || tp.x >= 3 || tp.y >= 3) continue;
tp.mz[now.x][now.y] = tp.mz[tp.x][tp.y];
tp.mz[tp.x][tp.y] = 'X';
int htp = _hash(tp);
if(vis[htp]) continue;
vis[htp] = true;
pre[x][htp] = hnow;
op[x][htp] = to_s[i];
q.push(tp);
}
}
}
int main(){
#ifdef sxk
freopen("in.txt", "r", stdin);
#endif // sxk
start = Node("X12345678"); bfs(0);
start = Node("1X2345678"); bfs(1);
start = Node("12X345678"); bfs(2);
start = Node("123X45678"); bfs(3);
start = Node("1234X5678"); bfs(4);
start = Node("12345X678"); bfs(5);
start = Node("123456X78"); bfs(6);
start = Node("1234567X8"); bfs(7);
start = Node("12345678X"); bfs(8);
int T, p;
scanf("%d", &T);
for(int kase=1; kase<=T; kase++){
scanf("%s", str);
for(int i=0, j=0; str[i]; i++){
if(str[i] == 'X') p = i;
else num[str[i]-'0'] = j++;
}
scanf("%s", str);
for(int i=0; str[i]; i++){
if(str[i] == 'X') continue;
str[i] = num[str[i]-'0'] + '1';
}
start = Node(str);
int hs = _hash(start);
string ans = "";
while(hs != -1){
ans += op[p][hs];
hs = pre[p][hs];
}
printf("Case %d: %d\n", kase, ans.size()-1); //有一个是起始位置,要减去
for(int i=ans.size()-2; i>=0; i--) putchar(ans[i]); //注意输出
puts("");
}
return 0;
}