zoukankan      html  css  js  c++  java
  • POJ 1077 && HDU 1043 Eight A*算法,bfs,康托展开,hash 难度:3

    http://poj.org/problem?id=1077

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

    X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0!。这就是康托展开。康拓展开可以用来表示排列状态,对于本题的9个数字的所有排列只需要9位,所有状态总共362880个.对每个状态,我们都能得到一个不重复的状态编号,用这个状态编号可以查重

    Astar算法,就是一个给所有状态一个评估函数,优先选取较优状态向下搜的最好优先直接搜索算法,对于本题,我们设F(n)=g(n)+h(n)为估价函数,设g(n)为到达该状态已经走过的步数,h(n)为到最终答案的曼哈顿距离

    因为该拼图不能改变除了x以外的数字的逆序数奇偶性,所以若x以外的数字逆序数为奇数,则无法得到答案,直接输出

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <cctype>
    using namespace std;
    const int base[9]={1,1,2,6,24,120,720,5040,40320};
    const int dx[4]={1,-1,0,0};
    const int dy[4]={0,0,1,-1};
    const int maxh=362880;
    const int des=0;
    struct pnt{
            int maz[3][3];
            int h,g;
            int x,y;
            int hashCode;
            bool operator < (pnt p)const {
                    return h+g!=p.h+p.g?h+g>p.h+p.g:g>p.g;
            }
            int gethashcode(){
                    int ans=0;
                    for(int i=0;i<9;i++){
                            int cnt=0;
                            for(int j=0;j<i;j++){
                                    if(maz[j/3][j%3]>maz[i/3][i%3]){
                                            cnt++;
                                    }
                            }
                            ans+=base[i]*cnt;
                    }
                    return hashCode=ans;
            }
            int geth(){
                    int ans=0;
                    for(int i=0;i<3;i++){
                            for(int j=0;j<3;j++){
                                    int t=maz[i][j]-1;
                                   if(t<9) ans+=abs(i-t/3)+abs(j-t%3);
                            }
                    }
                    return ans;
            }
            bool judge(){
                    int cnt=0;
                    for(int i=0;i<9;i++){
                            for(int j=0;j<i;j++){
                                    if(maz[i/3][i%3]<9&&maz[j/3][j%3]<9&&maz[i/3][i%3]<maz[j/3][j%3])cnt++;
                            }
                    }
                    return (cnt&1)==0;
            }
    };
    bool in(int tx,int ty){
            return tx>=0&&tx<3&&ty>=0&&ty<3;
    }
    
    int vis[maxh+1];
    int pre[maxh+1];
    
    void astar(pnt s){
            priority_queue <pnt>que;
            que.push(s);
            while(!que.empty()){
                    pnt f=que.top();que.pop();
                    for(int i=0;i<4;i++){
                            pnt t=f;
                            t.x+=dx[i];
                            t.y+=dy[i];
                            if(in(t.x,t.y)){
                                    swap(t.maz[t.x][t.y],t.maz[f.x][f.y]);
                                    t.hashCode=t.gethashcode();
                                    if(vis[t.hashCode]==-1){
                                            vis[t.hashCode]=i;
                                            t.g++;
                                            pre[t.hashCode]=f.hashCode;
                                            t.h=t.geth();
                                            que.push(t);
                                    }
                                    if(t.hashCode==des)return ;
                            }
                    }
            }
    }
    char ans[maxh+1];
    void print(){
            int nxt=des;
            int len=0;
            while(pre[nxt]!=-1){
                   switch(vis[nxt]){
                   case 0:
                           ans[len++]='d';
                    break;
                   case 1:
                           ans[len++]='u';
                    break;
                   case 2:
                           ans[len++]='r';
                    break;
                   case 3:
                           ans[len++]='l';
                    break;
                   }
                   nxt=pre[nxt];
            }
            for(int i=len-1;i>=0;i--){
                    putchar(ans[i]);
            }
            puts("");
    }
    char buff[300];
    pnt s;
    bool input(){
            if(gets(buff)==NULL)return false;
            int j=0;
            for(int i=0;i<9;i++){
                    while(!isalnum(buff[j])){j++;}
                    if(buff[j]>='0'&&buff[j]<='9'){
                            s.maz[i/3][i%3]=buff[j]-'0';
                    }
                    else{
                            s.maz[i/3][i%3]=9;
                            s.x=i/3;
                            s.y=i%3;
                    }
                    j++;
            }
            return true;
    }
    int main(){
            while(input()){
                    memset(vis,-1,sizeof(vis));
                    memset(pre,-1,sizeof(pre));
                    if(!s.judge()){
                            puts("unsolvable");
                            continue;
                    }
                    s.hashCode=s.gethashcode();
                    if(s.hashCode==des){
                            puts("");
                            continue;
                    }
                    vis[s.hashCode]=-2;
                    s.g=0;s.h=s.geth();
                    astar(s);
                    print();
            }
            return 0;
    }
    

      

  • 相关阅读:
    微信小程序的scheme码
    微信小程序的简单总结(uni-app)
    ES7-ES11新特性
    Promise 总结
    uni-app创建项目及使用 vant-weapp
    vscode 插件整理
    el-upload 组件总结
    从输入URL到页面显示过程中发生了什么
    实验 1:Mininet 源码安装和可视化拓扑工具
    2020软件工程第一次作业
  • 原文地址:https://www.cnblogs.com/xuesu/p/4344103.html
Copyright © 2011-2022 走看看