zoukankan      html  css  js  c++  java
  • 八数码[POJ1077 | HDU1043] BFS A* IDA* 双广

      八数码问题,对于一般的数据,BFS+逆序对HASH就可以解决了,或者双广搜索。进一步的话就是A*优化,A*的启发函数有以下两种:1,不在相应位置的格子数目;  2,不在相应位置的曼哈顿距离之和;显然第二种的效率比较高。一中兼顾效率,写起来有方便的算法就是IDA*,因为不要判重,而且是DFS,代码量小。还有猥琐点的方式就是从目标状态向所有状态扩展打表。。。

      对于八数码问题,还有一个重要剪枝,那就是逆数对的剪枝,如果开始状态的逆数对数目是奇数则必无解,否则一定有解。因为对于目标状态的逆序对是0,即偶数,而操作只能与0交换,而0是不会影响结果的,只有于0交换的数会影响结果,但是那个数移动也会没有影响,因此初始状态逆序对数为奇数不可能会转到偶数的状态,因此无解。

      其中对于POJ-1077和HDU-1043这两道题,因为只要求出可行解,没有必要求出步数最少的解,因此我们完全可以自己构造解,相信玩过拼图游戏并且思考了的就是小case了,简而言之就是一个一个的按照1,2,,,8,0的顺序把格子放回原位并且固定,再去放其它的,直到目标状态为止。

      下面是我的HDU1043 A*代码:

      1 //STATUS:C++_AC_328MS_4744KB
      2 #include<stdio.h>
      3 #include<stdlib.h>
      4 #include<string.h>
      5 #include<math.h>
      6 #include<iostream>
      7 #include<string>
      8 #include<algorithm>
      9 #include<vector>
     10 #include<queue>
     11 #include<stack>
     12 #include<map>
     13 #include<set>
     14 using namespace std;
     15 //define
     16 #define pii pair<int,int>
     17 #define mem(a,b) memset(a,b,sizeof(a))
     18 #define lson l,mid,rt<<1
     19 #define rson mid+1,r,rt<<1|1
     20 #define PI acos(-1.0)
     21 //typedef
     22 typedef long long LL;
     23 typedef unsigned long long ULL;
     24 //const
     25 const int N=210;
     26 const int INF=0x3f3f3f3f;
     27 const int MOD=1000007,STA=400010;
     28 const LL LNF=1LL<<60;
     29 const double EPS=1e-8;
     30 const double OO=1e15;
     31 const int dx[4]={-1,0,1,0};
     32 const int dy[4]={0,1,0,-1};
     33 //Daily Use ...
     34 template<class T> inline T Min(T a,T b){return a<b?a:b;}
     35 template<class T> inline T Max(T a,T b){return a>b?a:b;}
     36 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
     37 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
     38 //End
     39 
     40 char out[]="urdl";
     41 int fac[10];
     42 int T,end;
     43 
     44 struct Path{
     45     int op,fa;
     46 }path[STA];
     47 
     48 struct Node{
     49     int ma[9];
     50     int sta,g,h,x,y;
     51     bool operator < (const Node& b)const{
     52         return h!=b.h?h>b.h:g>b.g;
     53     }
     54 };
     55 
     56 struct HASH{
     57     int sta[STA];
     58     void init(){mem(sta,0);}
     59     int ctadd(int s[]){
     60         int i,j,ret=0,k;
     61         for(i=0;i<9;i++){
     62             for(j=k=0;j<i;j++)
     63                 if(s[j]>s[i])k++;
     64             ret+=k*fac[i];
     65         }
     66         if(sta[ret])return -1;
     67         sta[ret]=1;
     68         return ret;
     69     }
     70 }hs;
     71 
     72 int geth(int s[])
     73 {
     74     int i,j,h=0,x,y;
     75     for(i=0;i<3;i++){
     76         for(j=0;j<3;j++){
     77             x=s[i*3+j]/3;
     78             y=s[i*3+j]%3;
     79             h+=abs(x-i)+abs(y-j);
     80         }
     81     }
     82     return h;
     83 }
     84 
     85 int isok(int s[])
     86 {
     87     int i,j,cnt;
     88     for(i=cnt=0;i<9;i++){
     89         for(j=i+1;j<9;j++)
     90             if(s[i]!=8 && s[j]!=8 && s[i]>s[j])cnt++;
     91     }
     92     return !(cnt&1);
     93 }
     94 
     95 int astar(int s[])
     96 {
     97     int i,j;
     98     Node u,v;
     99     priority_queue<Node> q;
    100     for(i=0;i<9;i++)u.ma[i]=s[i];
    101     u.sta=hs.ctadd(s);
    102     u.g=0;u.h=geth(s);
    103     for(i=0;i<9;i++)if(s[i]==8){u.x=i/3,u.y=i%3;break;}
    104     q.push(u);
    105     path[u.sta].fa=-1;
    106     while(!q.empty()){
    107         u=q.top();q.pop();
    108         for(i=0;i<4;i++){
    109             v.x=u.x+dx[i];
    110             v.y=u.y+dy[i];
    111             if(v.x>=0&&v.x<3 && v.y>=0&&v.y<3){
    112                 for(j=0;j<9;j++)v.ma[j]=u.ma[j];
    113                 v.ma[v.x*3+v.y]=u.ma[u.x*3+u.y];
    114                 v.ma[u.x*3+u.y]=u.ma[v.x*3+v.y];
    115                 v.sta=hs.ctadd(v.ma);
    116                 if(v.sta>=0){
    117                     path[v.sta].op=i;
    118                     path[v.sta].fa=u.sta;
    119                     v.g=u.g+1;
    120                     v.h=geth(v.ma);
    121                     q.push(v);
    122                 }
    123                 if(v.sta==end){
    124                     return v.sta;
    125                 }
    126             }
    127         }
    128     }
    129     return -1;
    130 }
    131 
    132 void print(int u)
    133 {
    134     if(path[u].fa==-1)return;
    135     print(path[u].fa);
    136     printf("%c",out[path[u].op]);
    137 }
    138 
    139 int main()
    140 {
    141  //   freopen("in.txt","r",stdin);
    142     int i,j,s[10],ans;
    143     char c[N];
    144     fac[0]=1;
    145     for(i=1;i<9;i++)fac[i]=i*fac[i-1];
    146     end=0;
    147 
    148     while(gets(c)){
    149         for(i=j=0;c[i];i++){
    150             if(c[i]!=' '){
    151                 if(c[i]=='x')s[j]=8;
    152                 else s[j]=c[i]-'1';
    153                 j++;
    154             }
    155         }
    156 
    157         for(i=0,j=1;i<9;i++)if(s[i]!=i){j=0;break;}
    158         if(j){
    159             putchar('\n');
    160             continue;
    161         }
    162         if(isok(s)){
    163             hs.init();
    164             ans=astar(s);
    165             print(ans);
    166         }
    167         else printf("unsolvable");
    168         putchar('\n');
    169     }
    170     return 0;
    171 }
  • 相关阅读:
    #Linux 系统管理命令 | top命令
    Linux 操作文件目录
    背包问题(1)背包的引入
    硬币找零问题
    输入一个正数 n,输出所有和为 n 连续正数序列。 java实现
    张小二求职记之 单例模式(三)之决战多线程
    张小二求职 之单例模式(一)
    张小二求职记之 单例模式(二)
    待修改 nyoj 412 又是一个遗留问题
    nyoj 904 hashmap
  • 原文地址:https://www.cnblogs.com/zhsl/p/3052471.html
Copyright © 2011-2022 走看看