zoukankan      html  css  js  c++  java
  • hdu 1043 八数码问题-A*搜索

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

    题意。。不再赘述,和小时候玩的玩具很像。

    思路:今天人生终于完整了。。。

     来一个普通的A*搜索的思路。。。(感觉会不会倒着打表更快?)

    所谓A*搜索个人理解就是对于BFS的一个优先级队列优化。。。至于用什么作为关键字就是一个F(F=H+G) 

    H是估价函数,表示距离答案还有大约多少,越近H越高。。G是已花代价。。当然对于这个题目G并没有什么用,因为我们并不求最优,所以不如直接去直接以H作为关键字。

    对于本题,和最终答案越一样那么就越应该先搜索,所以将9个数字的和本来应该在的位置的曼哈顿距离加起来就可以判断是不是更接近目标了。。

    所以我们就可以设计一个看起来还不错的H函数。。。

    有了估价函数就很愉快的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;
    }
    
    int val(int x){
        int c=0,ret=0;
        while(x){
            tmp[c++]=x%10;
            ret+=abs((c-1)%3-(tmp[c-1]-1)%3)+abs((c-1)/3-(tmp[c-1]-1)/3);
            x/=10;
        }
        return -ret;
    }
    
    struct node{
        int val,num,id;
        node(){};
        node(int a,int b,int c):val(a),num(b),id(c){};
    };
    
    bool operator <(const node &a,const node &b){
        return a.val<b.val;
    }
    
    bool Astar(){
        memset(vis,0,sizeof(vis));
        memset(last,-1,sizeof(last));
        priority_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(0,x,cnt++));
        vis[Cantor(x,9)]=1;
        while(!P.empty()){
            node t=P.top();
            P.pop();
            ans=t.id;
            if(t.num==987654321) return true;
            if(cnt>2000) return false;
            for(int i=0;i<4;i++){
                int x=tran(t.num,i);
                if(x!=-1&&vis[Cantor(x,9)]==0){
                    vis[Cantor(x,9)]=1;
                    last[cnt]=t.id;
                    how[cnt]=i;
                    P.push(node(val(x),x,cnt++));
                }
            }
        }
        return false;
    }
    
    char re[maxn];
    
    void pr(int x){
        int c=0;
        while(x!=0){
            if(how[x]==0) re[c++]='u';
            else if(how[x]==1) re[c++]='r';
            else if(how[x]==2) re[c++]='d';
            else if(how[x]==3) re[c++]='l';
            x=last[x];
        }
        for(int i=c-1;i>=0;i--) printf("%c",re[i]);
        puts("");
    }
    
    int main(){
        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');
            }
            if(Astar()){
                //cout<<"ANS"<<ans<<endl;
                pr(ans);
            }
            else{
                puts("unsolvable");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    java下Mysql基本操作
    利用CNN进行多分类的文档分类
    对WEB url 发送POST请求
    Linq转换操作之OfType,Cast,AsEnumerable,ToLookup源码分析
    Linq转换操作之ToArray,ToList,ToDictionary源码分析
    Linq基础必备
    var 在linq中的使用
    Linq的使用场景简介和认识
    replaceState 实现返回从新定位
    ReSharper
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672536.html
Copyright © 2011-2022 走看看