HDU 1043 Eight(A*+HASH+康托展開)
31032 ワード
Eight
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13956 Accepted Submission(s): 3957 Special Judge
Problem Description
The 15-puzzle 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 sliding tiles, 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 call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as:
Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).
In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three arrangement.
Input
You will receive, several descriptions of configuration of the 8 puzzle. One description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle
1 2 3 x 4 6 7 5 8
is described by this list:
1 2 3 x 4 6 7 5 8
Output
You will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Do not print a blank line between cases.
Sample Input
2 3 4 1 5 x 7 6 8
Sample Output
ullddrurdllurdruldr
この問題は生々しく5日間やったので、A*とコントの展開を学んだ.自分で書いたが、まだよく分からない.「もしあなたが本当に知っていたら、自分で作るべきだ」という言葉があったが、私はまだ本当に理解していないようだ.
まず各行列の構造を構造に格納し,次に行列全体をカント展開でハッシュし,このような状況が現れたか,あるいは終点に達したかを判断する値を得た.したがって,初期の場合の逆序数が奇数であれば不可解である.
分からないところはA*の評価関数がなぜf=g+hではなく、hとgをそれぞれ2つのパラメータとして比較するのか、最初は2つのパラメータの位置を逆にして、1日Tしました.涙ばかりです.
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13956 Accepted Submission(s): 3957 Special Judge
Problem Description
The 15-puzzle 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 sliding tiles, 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 call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered 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 shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle: 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, respectively. Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).
In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three arrangement.
Input
You will receive, several descriptions of configuration of the 8 puzzle. One description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle
1 2 3 x 4 6 7 5 8
is described by this list:
1 2 3 x 4 6 7 5 8
Output
You will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Do not print a blank line between cases.
Sample Input
2 3 4 1 5 x 7 6 8
Sample Output
ullddrurdllurdruldr
この問題は生々しく5日間やったので、A*とコントの展開を学んだ.自分で書いたが、まだよく分からない.「もしあなたが本当に知っていたら、自分で作るべきだ」という言葉があったが、私はまだ本当に理解していないようだ.
まず各行列の構造を構造に格納し,次に行列全体をカント展開でハッシュし,このような状況が現れたか,あるいは終点に達したかを判断する値を得た.したがって,初期の場合の逆序数が奇数であれば不可解である.
分からないところはA*の評価関数がなぜf=g+hではなく、hとgをそれぞれ2つのパラメータとして比較するのか、最初は2つのパラメータの位置を逆にして、1日Tしました.涙ばかりです.
1 #include <iostream>
2 #include <cmath>
3 #include <string>
4 #include <queue>
5 #include <cstdio>
6 #include <cstring>
7 #include <algorithm>
8 using namespace std;
9
10 const int SIZE = 5;
11 const int GOAL = 46233;
12 const int HASH[] = {40320,5040,720,120,24,6,2,1,1};
13 const int UP_DATE[][2] = {{0,-1},{0,1},{-1,0},{1,0}};
14 int PATH[600000];
15 int PRE[600000];
16 struct Node
17 {
18 int map[SIZE][SIZE];
19 int x,y;
20 int h,g;
21 int hash;
22 bool operator <(const Node a) const
23 {
24 return h != a.h ? h > a.h : g > a.g;
25 }
26 };
27
28 bool solve_able(const Node & r);
29 bool check(const int,const int);
30 void cal_hash(Node & r);
31 void cal_h(Node & r);
32 void search(const Node & r);
33 void show(void);
34 int main(void)
35 {
36 Node first;
37 char s[50];
38
39 while(gets(s))
40 {
41 int k = 0;
42 memset(PRE,-1,sizeof(PRE));
43 memset(PATH,-1,sizeof(PATH));
44 for(int i = 1;i <= 3;i ++)
45 for(int j = 1;j <= 3;j ++)
46 {
47 if(s[k] >= '1' && s[k] <= '9')
48 first.map[i][j] = s[k] - '0';
49 else if(s[k] == 'x')
50 {
51 first.map[i][j] = 0;
52 first.x = i;
53 first.y = j;
54 }
55 else
56 j --;
57 k ++;
58 }
59 if(!solve_able(first))
60 {
61 printf("unsolvable
");
62 continue;
63 }
64 cal_hash(first);
65 if(first.hash == GOAL)
66 {
67 puts("");
68 continue;
69 }
70 PATH[first.hash] = -2;
71 first.g = 0;
72 cal_h(first);
73 search(first);
74 }
75
76 return 0;
77 }
78
79 bool solve_able(const Node & r)
80 {
81 int sum = 0,count = 0;
82 int temp[10];
83
84 for(int i = 1;i <= 3;i ++)
85 for(int j = 1;j <= 3;j ++)
86 {
87 temp[count] = r.map[i][j];
88 count ++;
89 }
90 for(int i = 0;i < 9;i ++)
91 for(int j = i + 1;j < 9;j ++)
92 if(temp[j] < temp[i] && temp[j] && temp[i])
93 sum ++;
94 return !(sum & 1);
95 }
96
97 bool check(const int x,const int y)
98 {
99 if(x >= 1 && x <= 3 && y >= 1 && y <= 3)
100 return true;
101 return false;
102 }
103
104 void cal_hash(Node & r)
105 {
106 int sum = 0,count = 0,box;
107 int temp[10];
108
109 for(int i = 1;i <= 3;i ++)
110 for(int j = 1;j <= 3;j ++)
111 {
112 temp[count] = r.map[i][j];
113 count ++;
114 }
115 for(int i = 0;i < 9;i ++)
116 {
117 box = 0;
118 for(int j = i + 1;j < 9;j ++)
119 if(temp[j] < temp[i])
120 box ++;
121 sum += (box * HASH[i]);
122 }
123 r.hash = sum;
124 }
125
126 void search(Node const & r)
127 {
128 Node cur,next;
129
130 priority_queue<Node> que;
131 que.push(r);
132 while(!que.empty())
133 {
134 cur = que.top();
135 que.pop();
136 for(int i = 0;i < 4;i ++)
137 {
138 next = cur;
139 next.x = cur.x + UP_DATE[i][0];
140 next.y = cur.y + UP_DATE[i][1];
141 if(!check(next.x,next.y))
142 continue;
143 swap(next.map[cur.x][cur.y],next.map[next.x][next.y]);
144 cal_hash(next);
145
146 if(PATH[next.hash] == -1)
147 {
148 PATH[next.hash] = i;
149 PRE[next.hash] = cur.hash;
150 next.g ++;
151 cal_h(next);
152 que.push(next);
153 }
154 if(next.hash == GOAL)
155 {
156 show();
157 return ;
158 }
159 }
160 }
161
162 }
163
164 void cal_h(Node & r)
165 {
166 int ans = 0;
167 for(int i = 1;i <= 3;i ++)
168 for(int j = 1;j <= 3;j ++)
169 if(r.map[i][j])
170 ans += abs(i - ((r.map[i][j] - 1) / 3 + 1)) + abs(j - ((r.map[i][j] - 1) % 3 + 1));
171 r.h = ans;
172 }
173
174 void show(void)
175 {
176 string ans;
177 int hash = GOAL;
178
179 ans.clear();
180 while(PRE[hash] != -1)
181 {
182 switch(PATH[hash])
183 {
184 case 0:ans += 'l';break;
185 case 1:ans += 'r';break;
186 case 2:ans += 'u';break;
187 case 3:ans += 'd';break;
188 }
189 hash = PRE[hash];
190 }
191 for(int i = ans.size() - 1;i >= 0;i --)
192 printf("%c",ans[i]);
193 cout << endl;
194 }