hdu 1043 Eight経典八数コード問題

33051 ワード

テーマリンク:http://acm.hdu.edu.cn/showproblem.php?pid=1043
The 15-puzle has been around for over 100 years;even if you don't know it by that name,you've seen it.It is constructed with 15 sland tile s,each with a number from 1 to 15 on it,and all packed into a 4 by 4 frame with one tile missing.Let's cal the missing。the object of the puzle is to arrange the tiles so that the y ardersed as:

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 x
where the only legal operation is to exchange'x'with one of the tiles with which it shres and edge.As_example,the following sequence of moves solight a slamble putzle:

1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
r-> d-> r->
The letters in the previous row indicate which neighbor of the'x'tile is swapped with the'x'tile at each step;legal values are'r',l',u'and'd',for right,left,up,and down,respively.
Not all puzles can be soloved;n 1870,a man named Sam Loyd was famous for distributing an unsoluble version of the puzle,and
fustringmany people.In fact,all you have to to make a reglar puzle into an soluble one is to swap two tiles.
In this proble、you will write a program for soling the less well-known 8-puzle、compsed of tiles on a three by three
arrangement.
 
一つの3を与える。×3の行列(1~8の数字と1文字xを含む)は、いくつかの移動格子上の数を経て連続する1~8を得て、最後の1マスはxで、最小移動ステップ数を求めます。
アルゴリズム解析:古典的な八数コード問題。八数コードは検索の問題です。古典的な解法はbfs、A*、IDA*などがあります。インターネットの資料が多いので、ここで簡単にA*を紹介します。
A*:f=g+h関数です。gは始点から現在点までの移動ステップ数を表し、hは現在点から目標点までの最小移動ステップ数の予測を表します。出発点と目標点を除いて、私達は任意の点を歩く時、次のステップはfより小さい継続を選ぶべきだと考えられます。(hの計算についてはマンハッタン距離の公式を使うことができます。)
カント展開:この問題の中の役割はhash関数を実施することにあります。現在のこのステップの後に新しい行列が得られます。カント展開式でこのマトリックスのhash値を計算して、幅検索で判断します。
もう一つの最適化点があります。現在の行列が目標行列に達するかどうかを判断します。(マトリックスの中の二つの数を交換した後、逆の順序のパリティと目標行列が一致してこそ、目標行列に到達する機会があります。)
  1 #include<iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 #include<cstdlib>

  5 #include<cmath>

  6 #include<algorithm>

  7 #include<queue>

  8 #include<vector>

  9 #define inf 0x7fffffff

 10 using namespace std;

 11 const int maxn=10;

 12 const int M = 400000+10;

 13 

 14 struct node

 15 {

 16     int mase[3][3];

 17     int x,y;

 18     int f,g,h;

 19     int flag;

 20     friend bool operator < (node a,node b)

 21     {

 22         return a.f > b.f;

 23     }

 24 }start,tail;

 25 int pre[M],v[M];

 26 

 27 char str[4]={'u','d','l','r' };

 28 int Can[10]={1,1,2,6,24,120,720,5040,40320 };

 29 const int destination=46234;

 30 int Cantor(node cur) ///    

 31 {

 32     int an[10],k=0;

 33     for (int i=0 ;i<3 ;i++)

 34         for (int j=0 ;j<3 ;j++)

 35             an[k++]=cur.mase[i][j];

 36     int sum=0;

 37     for (int i=0 ;i<9 ;i++)

 38     {

 39         int k=0;

 40         for (int j=i+1 ;j<9 ;j++)

 41             if (an[i]>an[j]) k++;

 42         sum += k*Can[9-i-1];

 43     }

 44     return sum+1;

 45 }

 46 

 47 int is_ok(node an) ///       

 48 {

 49     int a[10],k=0;

 50     for (int i=0 ;i<3 ;i++)

 51         for (int j=0 ;j<3 ;j++)

 52             a[k++]=an.mase[i][j];

 53     int sum=0;

 54     for (int i=0 ;i<k ;i++) if (a[i]!=0)

 55         for (int j=0 ;j<i ;j++)

 56             if (a[j]!=0 && a[j]>a[i]) sum ++ ;

 57     if (sum&1) return 0;

 58     return 1;

 59 }

 60 

 61 void print(node cur)

 62 {

 63     string ans;

 64     int sum=destination;

 65     while (pre[sum] != -1)

 66     {

 67         switch (v[sum]) {

 68         case 0 : ans += str[0];break;

 69         case 1 : ans += str[1];break;

 70         case 2 : ans += str[2];break;

 71         case 3 : ans += str[3];break;

 72         }

 73         sum=pre[sum];

 74     }

 75     int len=ans.size() ;

 76     for (int i=len-1 ;i>=0 ;i--) putchar(ans[i]);

 77     return ;

 78 }

 79 

 80 pair<int,int> pii[10];

 81 int getH(node cur)

 82 {

 83     int r=0,c=0;

 84     for (int i=1 ;i<=9 ;i++)

 85     {

 86         pii[i%9].first=r ;

 87         pii[i%9].second=c;

 88         c++;

 89         if (c==3) {r++;c=0; }

 90     }

 91     int sum=0;

 92     for (int i=0 ;i<3 ;i++)

 93     {

 94         for (int j=0 ;j<3 ;j++)

 95         {

 96             int u=cur.mase[i][j];

 97             sum += abs(pii[u].first-i)+abs(pii[u].second-j);

 98         }

 99     }

100     return sum;

101 }

102 

103 int vis[M];

104 int an[4][2]={-1,0, 1,0, 0,-1, 0,1 };

105 void A_star(node cur)

106 {

107     priority_queue<node> Q;

108     cur.g=0 ;cur.h=getH(cur);

109     cur.f=cur.g + cur.h ;

110     cur.flag=-1;

111     Q.push(cur);

112     memset(vis,-1,sizeof(vis));

113     memset(pre,-1,sizeof(pre));

114     memset(v,-1,sizeof(v));

115     vis[Cantor(cur) ]=1;

116     while (!Q.empty())

117     {

118         cur=Q.top() ;Q.pop() ;

119         if (Cantor(cur)==destination)

120         {

121 //            cout<<cur.g<<endl;

122 //            for (int i=0 ;i<3 ;i++)

123 //            {

124 //                for (int j=0 ;j<3 ;j++)

125 //                    cout<<cur.mase[i][j]<<" ";

126 //                cout<<endl;

127 //            }

128             ///    

129             print(cur);

130             return ;

131         }

132         for (int i=0 ;i<4 ;i++)

133         {

134             tail.x=cur.x+an[i][0];

135             tail.y=cur.y+an[i][1];

136             int x=cur.x ,y=cur.y ;

137             for (int u=0 ;u<3 ;u++)

138                 for (int v=0 ;v<3 ;v++)

139                     tail.mase[u][v]=cur.mase[u][v];

140             if (tail.x<0||tail.x>=3||tail.y<0||tail.y>=3) continue;

141             swap(tail.mase[tail.x][tail.y],tail.mase[x][y]);

142             int sum=Cantor(tail);

143             if (vis[sum]==-1)

144             {

145                 if (is_ok(tail)==0) continue;

146                 vis[sum]=1;

147                 tail.g=cur.g+1;

148                 tail.h=getH(tail);

149                 tail.f=tail.g+tail.h;

150                 if (tail.x==x+1) tail.flag=1;

151                 else if (tail.x==x-1) tail.flag=0;

152                 else if (tail.y==y-1) tail.flag=2;

153                 else if (tail.y==y+1) tail.flag=3;

154                 pre[sum]=Cantor(cur);

155                 v[sum]=i;

156                 Q.push(tail);

157             }

158         }

159     }

160     return ;

161 }

162 

163 int main()

164 {

165     char str[100];

166     while (gets(str))

167     {

168         int r=0,c=0;

169         int len=strlen(str);

170         int ok=0;

171         for (int i=0 ;i<len ;i++)

172         {

173             if (str[i]>='0' && str[i]<='9')

174             {

175                 start.mase[r][c]=str[i]-'0';

176                 c++;

177                 if (c==3) {r++;c=0; }

178             }

179             else if (str[i]=='x')

180             {

181                 start.mase[r][c]=0;

182                 start.x=r ;start.y=c ;

183                 c++;

184                 if (c==3) {r++;c=0; }

185             }

186         }

187         int sum=Cantor(start);

188         if (sum==destination) {printf("
");continue; } 189 if (is_ok(start)==0) {printf("unsolvable
");continue; } 190 A_star(start); 191 printf("
"); 192 } 193 return 0; 194 }