您的位置:首页 > 其它

HDU 3567 Eight II (A*)

2015-09-08 15:32 232 查看
题目链接: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: