关闭

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

245人阅读 评论(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网站的观点或立场

hdu 1043 Eight(八数码问题 高级搜索: A* 搜索)

Problem Description The 15-puzzle has been around for over 100 years; even if you don't know it b...
  • xiaosshhaa
  • xiaosshhaa
  • 2017-01-10 17:42
  • 214

POJ 1077 八数码 三种解法

POJ 1077 Eight题目链接:http://poj.org/problem?id=1077
  • lvxin1204
  • lvxin1204
  • 2016-05-31 13:41
  • 1280

hdu1043Eight (经典的八数码)(康托展开+BFS)

分类: 广搜2013-08-13 21:20 249人阅读 评论(0) 收藏 举报 树状BFS 建议先学会用康托展开:http://blog.csdn.net/u010372095/a...
  • pi9nc
  • pi9nc
  • 2014-05-29 22:23
  • 2895

八数码问题-启发式搜索(A*算法)

八数码问题是这样一个问题。有一个3x3大小的棋盘,上面放着标记有1~8八个数字的方形棋子,剩下一个区域为空。 每一次只能移动一个棋子到相邻的空区域上,8个棋子都移动到如下图所示的位置时,就结束了。
  • qq_32400847
  • qq_32400847
  • 2016-07-03 22:40
  • 3687

【启发式搜索】八数码问题

首先就是f(n)=g(n)+h(n)这个h(n)就是估价函数,然后每次更新一下g(n)然后用康托展开,搞一下判重就好了。#include #include #include #include ...
  • JeremyGJY
  • JeremyGJY
  • 2015-07-23 13:37
  • 664

【双向广搜+逆序数优化】【HDU1043】【八数码】

HDU上的八数码 数据强的一B 首先:双向广搜 先处理正向搜索,再处理反向搜索,直至中途相遇 visit 和 队列都是独立的。 可以用一个过程来完成这2个操作,减少代码量。(一般...
  • zy691357966
  • zy691357966
  • 2015-04-13 21:55
  • 1081

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

八数码问题,用的A*解决,但是数据太强A不了。。。TLE只能在POJ上先过一发了。#include #include #include #include #include #include ...
  • JeremyGJY
  • JeremyGJY
  • 2015-07-23 15:58
  • 427

Poj 1077 Eight 八数码问题 (搜索)

文章还没有写完,明天搞清楚IDA*算法再继续写。 搜索会用的方法太少了,于是最近被搜索虐爆了。。。 认识启发式搜索A*和迭代加深的A*算法:IDA*算法可以看这个: [搜索]A*和IDA*_c++...
  • whyorwhnt
  • whyorwhnt
  • 2013-08-29 22:08
  • 1270

HDU 1043 Eight(经典八数码问题)对比POJ 1077(bfs)

题目链接:点击打开链接 事情是这样的,我先在TLE无数发之后A了POJ的1077,然后在VJ上看到“原题”,然而,此原题被我TLE5发MLE9发,最后从学长那里学得记录路径的方法之后才过,却原来,...
  • tomorrowtodie
  • tomorrowtodie
  • 2016-07-06 01:30
  • 346

hdu 1043 Eight(八数码)

A*解法: #include #include #include #include #include #include #include #include #include #include #de...
  • u010697167
  • u010697167
  • 2014-03-16 19:52
  • 584
    个人资料
    • 访问:194442次
    • 积分:6924
    • 等级:
    • 排名:第3886名
    • 原创:522篇
    • 转载:3篇
    • 译文:0篇
    • 评论:12条
    文章分类
    最新评论