码迷,mamicode.com
首页 > 其他好文 > 详细

HDU-1043 八数码问题(A*解法)

时间:2020-09-15 21:01:35      阅读:31      评论:0      收藏:0      [点我收藏+]

标签:这一   建议   cstring   标准   star   space   abs   简介   展开   

简介:一个九宫格中有八个数字,一位空格,每次只能移动相邻的两个格子,现要求把九宫格变为“12345678x”的样子(x代表空格)

Sample Input

2  3  4  1  5  x  7  6  8

 

Sample Output

ullddrurdllurdruldr

 这里我们要用到康拓展开,具体介绍如下:

技术图片

技术图片

康拓展开并不难,相信各位能看懂,所以我们是把九宫格看成了一个字符串数组来解决;用BFS来寻找转移的方法,但是单纯的BFS容易TLE,那么好,我们这里就用到A*算法,A*算法其实并不难,在这里的BFS基础上我们加一个评估函数h(),h()是怎么评估的呢?是通过当前序列每个数字与标准情况下相比较(这个有点难说明白,建议看看一些迷宫类问题,即每走一步,在这一步到终点观望一下还剩多少距离)

通过使用一个优先队列,能降低时间复杂度。相比盲目的BFS来说,是一个相对比较“智能”的算法,代码如下:

#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
#define N 9

struct Point
{
    char eight[N];
    int position;
    int g,f;
    friend bool operator <(const Point& a,const Point& b)
    {
        return a.f > b.f;
    }
}startPoint;

const int fac[] = {1,1,2,6,24,120,720,5040,40320};//康托序列
const int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
const char option[4]={d,r,u,l};
bool visited[363000];
int pre[363000];
char op[363000];
stack<char> stk;

int cantor(Point p) //康拓展开
{
    int ans=0;
    for(int i=0 ;i<N ;i++)
    {
        int cnt = 0;
        for(int k=i+1 ;k<N ;k++)
            if(p.eight[k]>p.eight[i])
            cnt++;
        ans += fac[8-i]*cnt;
    }
    return ans;
}

int ABS(int x){return x<0? -x:x;}  //自定义绝对值
int h(Point p)                      //评估函数
{
    int val=0;
    for(int i=0 ;i<N ;i++)
    {
        if(p.eight[i]==x) continue;
        int c = p.eight[i]-1;
        val += ABS(c/3-i/3)+ABS(c%3-i%3);
    }
    return val;
}

bool bfs()
{
    int row,col,cantorValue;
    memset(visited,false,sizeof(visited));
    priority_queue<Point> que;
    que.push(startPoint);
    while(!que.empty())
    {
        Point p = que.top();
        que.pop();
        for(int i=0;i<4 ;i++)
        {
            row = p.position/3 +dir[i][0];
            col = p.position%3 +dir[i][1];
            if(row<0||col<0||row>=3||col>=3) continue;
            Point newPoint(p);
            newPoint.eight[newPoint.position] = newPoint.eight[col+row*3];
            newPoint.position = col+row*3;
            newPoint.eight[newPoint.position] = x;
            cantorValue = cantor(newPoint);
            if(visited[cantorValue]) continue;
            visited[cantorValue] = true;
            newPoint.g++;
            newPoint.f = newPoint.g +h(newPoint);
            pre[cantorValue] = cantor(p);
            op[cantorValue] = option[i];
            if(cantorValue==0) return true;

            que.push(newPoint);
        }
    }
    return false;
}

bool inversionNumberCheck()
{
    int cnt =0;
    for(int i=0 ;i<N ;i++)
    {
        if(startPoint.eight[i]==x) continue;
        for(int k=i+1;k<N ;k++)
        {
            if(startPoint.eight[k]==x) continue;
            if(startPoint.eight[k]<startPoint.eight[i])
                cnt++;
        }
    }
    return cnt&1;
}

int main()
{
    while(cin >> startPoint.eight[0])
    {
        if(startPoint.eight[0]==x)
            startPoint.position=0;
        for(int i=1 ;i<9 ;i++)
        {
            cin >> startPoint.eight[i];
            if(startPoint.eight[i]==x)
                startPoint.position=i;   //记录x所在的位置
        }
        if(inversionNumberCheck())
        {
            cout <<"unsolvable" <<endl;
            continue;
        }
        startPoint.g=0;
        startPoint.f = h(startPoint);
        int startCantor = cantor(startPoint);
        bfs();
        int index =0;
        while(index!=startCantor)
        {
            stk.push(op[index]);
            index = pre[index];
        }
        while(!stk.empty())
        {
            cout << stk.top();
            stk.pop();
        }
        cout << endl;
    }
}

 

HDU-1043 八数码问题(A*解法)

标签:这一   建议   cstring   标准   star   space   abs   简介   展开   

原文地址:https://www.cnblogs.com/yegowxx23/p/13599493.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!