hdu 1043 八数码 A*

本文介绍了一个利用曼哈顿距离作为估价函数的A*搜索算法实现,解决八数码问题。通过定义节点结构、计算哈希值、判断状态合法性等步骤,实现了从初始状态到目标状态的有效搜索,并输出最优解路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

曼哈顿距离作为估价函数。

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1043

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <vector>

#define maxn 400000

using namespace std;

struct Node{
    int a[10];
    int x,y;
    int g,h;
    int Hash;
    //bool operator < (const Node n1)const{
    //    return h!=n1.h?h>n1.h:g>n1.g;
    //}
    friend bool operator < (const Node & a1,const Node & a2){
        if(a1.h==a2.h)
            return a1.g < a2.g;
        else
            return a1.h > a2.h;
    }
    bool check(){
        if(x>=0&&x<3&&y>=0&&y<3)
            return true;
        else
            return false;
    }
}s,u,v,tt;

int Hct[10] ={1,1,2,6,24,120,720,5040,40320,362880};
int destination ;
char vis[maxn];
int  pre[maxn];
char d[5] = "rldu";
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};

void Dedug(Node tmp){
    int i;
    for(i=0;i<9;i++){
        printf("%d",tmp.a[i]);
    }
    puts("");
    printf("x : %d y : %d\n",tmp.x,tmp.y);
    printf("g : %d h : %d\n",tmp.g,tmp.h);
    printf("Hash : %d\n",tmp.Hash);
}

int ct(int * a){
    int i,j,con,zans = 0;
    for(i=0;i<8;i++){
        con = 0;
        for(j=i+1;j<9;j++){
            if(a[j]<a[i])con++;
        }
        zans += con * Hct[8-i];
    }
    return zans;
}


/*
int ct(int * a){
    int k=0,res=0;
    for(int i=0;i<9;i++){
        int k=0;
        for(int j=0;j<i;j++)
            if(a[j]>a[i])
                k++;
        res+=Hct[i]*k;
    }
    return res;
}
*/

bool i_sok(int * a){
    int con=0,i,j;
    for(i=0;i<8;i++){
        for(j=i+1;j<9;j++){
            if(a[i]&&a[j]&&a[j]<a[i]){
                con++;
            }
        }
    }
    return !(con&1);
}

int get_h(int * a){
    int ans=0;
    int i,j1,k1,j2,k2;
    for(i=0;i<9;i++){
        if(a[i]){
            j1 = (a[i]-1) / 3;
            k1 = (a[i]-1) % 3;
            j2 = i / 3;
            k2 = i % 3;
            ans += abs(j1-j2)+abs(k1-k2);
        }
    }
    return ans;
}

void Astar(){
    int i;
    priority_queue<Node>q;
    q.push(s);
    while(!q.empty()){
        u = q.top();
        q.pop();
        for(i=0;i<4;i++){
            v = u;
            int temp1 = v.x * 3 + v.y;
            v.x += dx[i];
            v.y += dy[i];
            if(v.check()){
                int temp2= v.x * 3 + v.y;
                v.a[temp1] = v.a[temp2];
                v.a[temp2] = 0;
                v.Hash = ct(v.a);
                if(vis[v.Hash]==-1){
                    vis[v.Hash] = d[i];
                    pre[v.Hash] = u.Hash;
                    v.h = get_h(v.a);
                    q.push(v);
                }
            }
            if(v.Hash==destination)
                return ;
        }
    }
}

void print(){
    string ans = "";
    int i,nxt = destination;
    while(pre[nxt]!=-1){
        ans+=vis[nxt];
        nxt = pre[nxt];
    }
    for(i=ans.length()-1;i>=0;i--){
        cout<<ans[i];
    }
    cout<<endl;
}

int main(void){
    //freopen("a.in","r",stdin);
    char tempa[105];
    int i,k;
    int Tmp[10] = {1,2,3,4,5,6,7,8,0};
    destination = ct(Tmp);
    while(gets(tempa)){
        memset(vis,-1,sizeof(vis));
        memset(pre,-1,sizeof(pre));
        k = 0;
        for(i=0;i<strlen(tempa);i++){
            if(tempa[i]>'0'&&tempa[i]<'9')
                s.a[k++] = tempa[i] - '0';
            if(tempa[i]=='x'){
                s.a[k++] = 0;
                s.x = (k - 1)/3;
                s.y = (k - 1)%3;
            }
        }
        if(!i_sok(s.a)){
            puts("unsolvable");continue;
        }
        s.Hash = ct(s.a);
        vis[s.Hash] = -2;
        if(s.Hash==destination){
            puts("");continue;
        }
        s.h = get_h(s.a);
        s.g = 0;
        //Dedug(s);
        Astar();
        print();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值