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

原创 2016年08月30日 13:11:02

题目链接
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;
}
版权声明:一个菜逼的笔记,并没有什么题解。。。

相关文章推荐

hdu 1043 poj 1077 Eight Time (搜索&八数码)

Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S...

hdu 1043/poj 1077 Eight (八数码 经典搜索题 bfs + 康托展开)

听说不做此题人生不完整,吓得我赶紧做了。

poj 1077 hdu 1043 Eight 八数码问题 DBFS(双向广度优先搜索)a*算法 康拓展开

一,八数码问题简介 编号为1到8的8个正方形滑块被摆成3行3列(有一个格子留空),可以每次把与空格相邻(有公共边)的滑块移动到空格中,而它原来的位置就成了新的空格。给定局面,计算出从当前状态移动到目标...
  • gwq5210
  • gwq5210
  • 2015年08月29日 20:40
  • 1006

HDU 1043 Eight 八数码问题 A*搜索 启发式算法

原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给一个3*3的方格,每个格子分别有1,2,3,4,5,6,7,8,x这九个编号,其中x...
  • dpppBR
  • dpppBR
  • 2016年07月31日 21:54
  • 647

hdu 1043 /poj 1077 Eight(经典八数码问题,BFS+康托展开)

Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S...
  • acm_cxq
  • acm_cxq
  • 2016年08月05日 21:58
  • 323

POJ 1077(HDU 1043) Eight(八数码A*算法)

通过演算发现每次一动,逆序对增加一定是偶数对,如果出现奇数则肯定不符合要求,所以要事先判断否则会超时。奇偶剪枝是一种非常常用的剪枝方法,如果在搜索中超时,可以尝试奇偶剪枝。 // // main.c...

POJ1077 HDU1043 Eight 八数码 (A*+康托展开)

题目大意:给出八数码的起点状态,求出能够到达到终点状态的步数的序列(不一定是要最短的步数) 终点状态为:1 2 3 4 5 6 7 8 x 思路:这道题有很多方法可以做,在这里我用的是...
  • cqbzwja
  • cqbzwja
  • 2015年07月26日 16:54
  • 263

【启发式搜索】[POJ 1077]Eight

八数码问题,用的A*解决,但是数据太强A不了。。。TLE只能在POJ上先过一发了。#include #include #include #include #include #include ...

POJ1077&HDU1043 Eight 八数码第七境界 AStar hash 康托展开 最小堆优化 奇偶剪枝

Description The 15-puzzle has been around for over 100 years; even if you don't know it by that n...

POJ1077&HDU1043 Eight 八数码第八境界 IDA* hash 康托展开 奇偶剪枝

Description The 15-puzzle has been around for over 100 years; even if you don't know it by that...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDU 1043 Eight poj 1077 (八数码 启发式搜索)
举报原因:
原因补充:

(最多只允许输入30个字)