Accepted | 6588K | 329MS | 3890B | 2013-05-20 23:43:40 |
康拓展开式: http://blog.csdn.net/xuruoxin/article/details/8951913
/**
* 这题做了我一晚上啊! 半晚上写代码,半晚上debug。 最后发现错在两个变量的名字上
* 闲话不说,总结:
* 搜索题: BFS 关键是要用到 康拓展开式来压缩空间。
* 在代码中用getState把一串数字字符,也就是全排列转换成自然数表示(按照康拓展开式)
* 结构体Node就是每个状态,保存数据:
* pre: 之前一个状态 type: 由之前状态转移到当前状态所采取的操作类型
* board: 就是3 * 3的图版 place: 在当前状态中,x所在的位置
* 经过BFS搜索,最终状态是 123456789, 其state是0(由康拓展开式得)
* 所以只要当curState为0的时候就是找到答案,记录答案后break就行。
* 最后,因为每个状态都存储了前一个状态,而且还记录了每种操作,只要往回搜到根节点,也就是pre = -1的那个就结束
* 把路径存入栈中,后输出即可。
* 花了半个晚上debug的错误: 就在对各状态转移时候的变量用错。。 place 和 cur.place (一个是结构体外的变量, 一个是结构体内变量) 害死我也。。。
* 反省: 是粗心? 还是思维不够缜密吧!!
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#define INF 0x7fffffff
#define MAXS 362881
#define LL long long
using namespace std;
int vis[MAXS], pre[MAXS], maps[3][3];
int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
int ans, front, rear, top;
char ansStack[MAXS];
struct Node {
char board[10];
int pre, state, place;
char type;
} que[MAXS];
int getState(const char *str) {
int state = 0;
for(int i = 1; i <= 8; i ++) {
int cnt = 0;
for(int j = i + 1; j <= 9; j ++)
if(str[i] > str[j]) cnt ++;
state += cnt * fac[9 - i];
}
return state;
}
void bfs(const Node &node) {
front = rear = 0;
memset(vis, 0, sizeof(vis));
que[rear++] = node;
Node cur;
int curState, place;
ans = -1;
vis[node.state] = 1;
while(front < rear) {
cur = que[front];
cur.pre = front;
place = cur.place;
if(cur.state == 0) {
ans = front;
break;
}
//BFS up down left right
if(place - 3 > 0) {
swap(cur.board[place], cur.board[place - 3]);
curState = getState(cur.board);
if(!vis[curState]) {
vis[curState] = 1;
cur.place = place - 3;
cur.state = curState;
cur.type = 'u';
que[rear++] = cur;
}
swap(cur.board[place], cur.board[place - 3]);
}
if(place + 3 < 10) {
swap(cur.board[place], cur.board[place + 3]);
curState = getState(cur.board);
if(!vis[curState]) {
vis[curState] = 1;
cur.place = place + 3;
cur.state = curState;
cur.type = 'd';
que[rear++] = cur;
}
swap(cur.board[place], cur.board[place + 3]);
}
if((place - 1) % 3 != 0) {
swap(cur.board[place], cur.board[place - 1]);
curState = getState(cur.board);
if(!vis[curState]) {
vis[curState] = 1;
cur.place = place - 1;
cur.state = curState;
cur.type = 'l';
que[rear++] = cur;
}
swap(cur.board[place], cur.board[place - 1]);
}
if((place + 1) % 3 != 1) {
swap(cur.board[place], cur.board[place + 1]);
curState = getState(cur.board);
if(!vis[curState]) {
vis[curState] = 1;
cur.place = place + 1;
cur.state = curState;
cur.type = 'r';
que[rear++] = cur;
}
}
front ++;
}
}
void print() {
if(ans == -1) {
printf("unsolvable\n");
return ;
}
top = 0;
while(ans != -1) {
ansStack[top++] = que[ans].type;
ans = que[ans].pre;
}
top -= 2;
while(top != -1) {
printf("%c", ansStack[top--]);
}
printf("\n");
}
int main()
{
char ch;
bool done = false;
while(!done) {
Node start;
start.pre = -1;
int i = 1;
while(1) {
if(scanf("%c", &ch) == EOF) {
done = true;
break;
}
if(ch == 'x') {
start.board[i] = 9;
start.place = i;
i ++;
} else if(ch >= '1' && ch <= '8'){
start.board[i++] = ch - '0';
}
if(i == 10)
break;
}
if(done) break;
start.state = getState(start.board);
bfs(start);
print();
}
return 0;
}