POJ 1077 Eight BFS + 康拓展开式

Accepted

6588K

329MS

C++

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;
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值