关闭

HDU 1043 Eight poj 1077 (八数码 启发式搜索)

196人阅读 评论(0) 收藏 举报
分类:

题目链接
poj1077
hdu1043

使用A*搜索就可以了
A*是bfs的一种优化,使用函数F做为每个节点的访问的优先级

hdu的需要先判断是否有解,否则会tle,加上后跑了1000+ms
poj的不用判断,也可以ac,跑了40+ms

奇偶判断解是否存在:

一个状态表示成一维的形式,求出除空白之外所有数字的逆序数之和,也就是每个数字前面比它大的数字的个数的和,称为这个状态的逆序。
若两个状态的逆序奇偶性 相同,则可相互到达,否则不可相互到达。
由于原始状态的逆序为0(偶数),则逆序为偶数的状态有解。

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
#define cl(a,b) memset(a,b,sizeof(a))
#define fastIO ios::sync_with_stdio(false);cin.tie(0);
#define LL long long
#define pb push_back
#define gcd __gcd


#define For(i,j,k) for(int i=(j);i<=k;i++)
#define lowbit(i) (i&(-i))
#define _(x) printf("%d\n",x)

typedef vector<LL> vec;
typedef pair<int,int> PI;
const double EPS = 1e-8;
const int maxn = 4e5;
const int inf  = 1 << 28;
int fac[10];
void init(){
    fac[0] = 1;
    for(int i=1;i<=9;i++)fac[i]=fac[i-1]*i;
}
int contor(int a[]){
    int ans = 0, n = 9;
    for(int i=0;i<n;i++){
        int tp = 0;
        for(int j=i+1;j<n;j++)if(a[j]<a[i])tp++;
        ans+=tp*fac[n-1-i];
    }
    return ans;
}
int getH(int a[]){
    int ret = 0;
    for(int i=0;i<9;i++){
        int x = i / 3;
        int y = i % 3;
        int xx = (a[i] - 1) / 3;
        int yy = (a[i] - 1) % 3;
        ret += abs(x-xx)+abs(y-yy);
    }
    return ret;
}


int dir[2][4]={0,0,-1,1,-1,1,0,0};
char *dirc = "lrud";
int vis[maxn];//closed list
struct node{
    int a[10];
    int x,y;
    int F,G,H;
    int id;
    bool isok(){
        if(x >= 0 && x <= 2 && y >= 0 && y <= 2)return true;
        return false;
    }
    bool operator<(const node&rhs) const{
        return F > rhs.F || F == rhs.F && G > rhs.G;
    }
}start,last,now;

struct path{
    int id,dir;
}fa[maxn];
int bfs(){
    priority_queue<node> q;
    cl(vis,false);

    q.push(start);

    while(!q.empty()){
        last = q.top();q.pop();

        for(int i=0;i<4;i++){
            now = last;
            now.x += dir[0][i];
            now.y += dir[1][i];
            if(!now.isok())continue;
            swap(now.a[last.x*3+last.y], now.a[now.x*3+now.y]);
            now.id = contor(now.a);
            if(vis[now.id])continue;
            now.G = last.G + 1;
            now.H = getH(now.a);
            now.F = now.G + now.H;
            fa[now.id] = (path){last.id,i};

            q.push(now);
            if(now.id == 0)return now.G;
        }
        vis[last.id] = true;
    }
    return -1;
}

bool isok(int a[]){
    int sum = 0;
    for(int i=0;i<9;i++){
        for(int j=i+1;j<9;j++){
            if(a[i]==9||a[j]==9)continue;
            if(a[i]>a[j])sum++;
        }
    }
    return sum%2 == 0;
}

char str[3];
vector<char> v;
int main(){
    init();
    while(~scanf("%s",str)){
        start.a[0] = str[0] == 'x' ? 9 : str[0] - '0';
        for(int i=1;i<=8;i++){
            scanf("%s",str);
            start.a[i] = str[0] == 'x' ? 9 : str[0] - '0';
        }
        //for(int i=0;i<9;i++)printf("%d ",start.a[i]);

        for(int i=0;i<9;i++)if(start.a[i]==9){start.x = i/3;start.y = i%3;break;}
        start.G = 0;
        start.H = getH(start.a);
        start.F = start.G + start.H;
        start.id = contor(start.a);

        if(start.id == 0){
            puts("");continue;
        }
        if(!isok(start.a)){
            puts("unsolvable");continue;
        }

        cl(fa,-1);

        int ans = bfs();

        if(ans == -1){
            puts("unsolvable");
        }
        else {
            v.clear();
            path t = fa[0];
            while(t.id!=-1){
                //printf("t = %d %d\n",t.id,t.dir);
                //putchar(dirc[t.dir]);
                v.pb(dirc[t.dir]);
                t = fa[t.id];
            }
            for(int i=v.size()-1;i>=0;i--){
                printf("%c",v[i]);
            }
            printf("\n");
        }

    }
    return 0;
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:168162次
    • 积分:6668
    • 等级:
    • 排名:第3665名
    • 原创:522篇
    • 转载:3篇
    • 译文:0篇
    • 评论:12条
    文章分类
    最新评论