hdu 1043 八数码--打表

本文介绍了一种使用A*搜索算法解决九宫拼图问题的方法,并提供了详细的代码实现。通过逆向BFS策略从目标状态出发寻找初始状态,有效解决了拼图问题。

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

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


题意:略;


思路:其实怎么看也是打表的思路比较容易想一些,不过A*搜索真是神奇。。。而且打表快不少,可能和多组数据有关,其实A*也可以记忆化一下应付一下多组数据,大概也会快不少吧。。。

思路很简单,从最终状态反向暴力BFS就可以了。。因为所有状态也已9!不是很多,主要用hash来去重就可以了。思维含量比A*简单。。


代码:

#include <bits/stdc++.h>

using namespace std;

const int dis[12] = {1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800};
int tmp[10];
char s[10];
const int maxn=1e5*4;
int arr[10];
int vis[maxn];
int last[maxn+10];
int how[maxn+10];
int ans=-1;

int Cantor(int x, int len){
    int c=0;
    while(x){
        tmp[c++]=x%10;
        x/=10;
    }
    int resl = 1;
    for(int i = 0; i < len; i++){
        int counts = 0;
        for(int k = i + 1; k < len; k++){
            if(tmp[i] > tmp[k]){
                counts++;
            }
        }
        resl = resl + dis[len-i-1] * counts;
    }
    return resl;
}



int tran(int x,int h){
    int c=0,ret=0,idx=0;;
    while(x){
        tmp[c++]=x%10;
        if(tmp[c-1]==9) idx=c-1;
        x/=10;
    }
    if(h==0){
        if(idx<3) return -1;
        else swap(tmp[idx],tmp[idx-3]);
    }
    else if(h==1){
        if(idx%3==2) return -1;
        else swap(tmp[idx],tmp[idx+1]);
    }
    else if(h==2){
        if(idx>5) return -1;
        else swap(tmp[idx],tmp[idx+3]);
    }
    else if(h==3){
        if(idx%3==0) return -1;
        else swap(tmp[idx],tmp[idx-1]);
    }
    for(int i=0,j=1;i<9;i++,j*=10) ret+=tmp[i]*j;
    return ret;
}

struct node{
    int num,id;
    node(){};
    node(int b,int c):num(b),id(c){};
};

bool Astar(){
    memset(vis,-1,sizeof(vis));
    memset(last,-1,sizeof(last));
    queue<node> P;
    int x=0,cnt=0;
    for(int i=0,j=1;i<9;i++,j*=10) x+=arr[i]*j;
    P.push(node(x,cnt++));
    vis[Cantor(x,9)]=1;
    while(!P.empty()){
        node t=P.front();
        P.pop();
        ans=t.id;
        for(int i=0;i<4;i++){
            int x=tran(t.num,i);
            if(x!=-1&&vis[Cantor(x,9)]==-1){
                vis[Cantor(x,9)]=cnt;
                last[cnt]=t.id;
                how[cnt]=i;
                P.push(node(x,cnt++));
            }
        }
    }
    return false;
}

char re[maxn];

void pr(int x){
    int c=0;
    while(x!=0){
        if(how[x]==0) re[c++]='d';
        else if(how[x]==1) re[c++]='l';
        else if(how[x]==2) re[c++]='u';
        else if(how[x]==3) re[c++]='r';
        x=last[x];
    }
    for(int i=0;i<c;i++) printf("%c",re[i]);
    puts("");
}

int main(){
    for(int i=0;i<9;i++) arr[i]=i+1;
    Astar();
    while(cin>>s[0]>>s[1]>>s[2]>>s[3]>>s[4]>>s[5]>>s[6]>>s[7]>>s[8]){
        for(int i=0;i<9;i++){
            if(s[i]=='x') arr[i]=9;
            else arr[i]=(int)(s[i]-'0');
        }
        int ret=0;
        for(int i=0,j=1;i<9;i++,j*=10) ret+=arr[i]*j;
        if(ret==987654321) puts("");
        else if(vis[Cantor(ret,9)]!=-1){
            pr(vis[Cantor(ret,9)]);
        }
        else{
            puts("unsolvable");
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值