八数码[POJ-1077 | HDU-1043] 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 }

 

你可能感兴趣的:(poj)