UVA_Cubic Eight-Puzzle UVA 1604
2015-05-04 12:09
363 查看
Let's play a puzzle using eight cubes placed on a 3 x 3 board leaving one empty square.
Faces of cubes are painted with three colors. As a puzzle step, you can roll one of the cubes to the adjacent
empty square. Your goal is to make the specified color pattern visible from above by a number of such steps.
The rules of this puzzle are as follows.
[b]Coloring of Cubes: All the cubes are colored in the same way as shown in Figure 3. The opposite
faces have the same color.
Figure 3: Coloring of a cube[/b]
[b]1.Initial Board State: Eight cubes are placed on the 3 x 3 board leaving one empty square. All the
cubes have the same orientation as shown in Figure 4. As shown in the figure, squares on the board
are given x and y coordinates, (1, 1), (1, 2), ..., and (3, 3). The position of the initially empty square
may vary.[/b]
Figure 4: Initial board state
[b]2.Rolling Cubes: At each step, we can choose one of the cubes adjacent to the empty square and roll it
into the empty square, leaving the original position empty. Figure 5 shows an example.
Figure 5: Rolling a cube[/b]
[b]3.Goal: The goal of this puzzle is to arrange the cubes so that their top faces form the specified color
pattern by a number of cube rolling steps described above.
4.Your task is to write a program that finds the minimum number of steps required to make the specified color
pattern from the given initial state.
Input
The input is a sequence of datasets. The end of the input is indicated by a line containing two zeros separated
by a space. The number of datasets is less than 16. Each dataset is formatted as follows.
x y
F
11 F21 F31
F
12 F22 F32
F
13 F23 F33
The first line contains two integers x and y separated by a space, indicating the position (x, y) of the initially
empty square. The values of x and y are 1, 2, or 3.
The following three lines specify the color pattern to make. Each line contains three characters F1j, F2j, and
F
3j, separated by a space. Character Fij indicates the top color of the cube, if any, at position (i, j) as follows:
B:
Blue,
W:
White,
R:
Red,
E:
the square is Empty.
There is exactly one `E' character in each dataset.
Output
For each dataset, output the minimum number of steps to achieve the goal, when the goal can be reached
within 30 steps. Otherwise, output ``-1'' for the dataset.
3618 - Cubic Eight-Puzzle 2/3
Sample Input
1 2
W W W
E W W
W W W
2 1
R B W
R W W
E W W
3 3
W B W
B R E
R B R
3 3
B W R
B W R
B E R
2 1
B B B
B R B
B R E
1 1
R R R
W W W
R R E
2 1
R R R
B W B
R R E
3 2
R R R
W E W
R R R
0 0
Sample Output
0
3
13
23
29
30
-1
-1
[/b]
解题报告
难度。。很大,BFS这个没有疑问,那么究竟是A*还是双广呢,由于本题的状态数很多,且转移方程很麻烦,所以首先考虑A*.
估价函数这里不在多说(其实是我忘了),但提交后TLE...,CODE如下
这里的代码中有Clock(),大家可以试试几组数据,30步的极限或者-1,速度非常慢。。(无法忍受)
那么,我们只能改用双广了,因为末状态有256种,所以我们用一个dfs把末状态压进去,提交后AC~
顺便多题一句双广复杂度是 2*n^(a/2) ,而单向的是n^a,code 如下
Faces of cubes are painted with three colors. As a puzzle step, you can roll one of the cubes to the adjacent
empty square. Your goal is to make the specified color pattern visible from above by a number of such steps.
The rules of this puzzle are as follows.
[b]Coloring of Cubes: All the cubes are colored in the same way as shown in Figure 3. The opposite
faces have the same color.
Figure 3: Coloring of a cube[/b]
[b]1.Initial Board State: Eight cubes are placed on the 3 x 3 board leaving one empty square. All the
cubes have the same orientation as shown in Figure 4. As shown in the figure, squares on the board
are given x and y coordinates, (1, 1), (1, 2), ..., and (3, 3). The position of the initially empty square
may vary.[/b]
Figure 4: Initial board state
[b]2.Rolling Cubes: At each step, we can choose one of the cubes adjacent to the empty square and roll it
into the empty square, leaving the original position empty. Figure 5 shows an example.
Figure 5: Rolling a cube[/b]
[b]3.Goal: The goal of this puzzle is to arrange the cubes so that their top faces form the specified color
pattern by a number of cube rolling steps described above.
4.Your task is to write a program that finds the minimum number of steps required to make the specified color
pattern from the given initial state.
Input
The input is a sequence of datasets. The end of the input is indicated by a line containing two zeros separated
by a space. The number of datasets is less than 16. Each dataset is formatted as follows.
x y
F
11 F21 F31
F
12 F22 F32
F
13 F23 F33
The first line contains two integers x and y separated by a space, indicating the position (x, y) of the initially
empty square. The values of x and y are 1, 2, or 3.
The following three lines specify the color pattern to make. Each line contains three characters F1j, F2j, and
F
3j, separated by a space. Character Fij indicates the top color of the cube, if any, at position (i, j) as follows:
B:
Blue,
W:
White,
R:
Red,
E:
the square is Empty.
There is exactly one `E' character in each dataset.
Output
For each dataset, output the minimum number of steps to achieve the goal, when the goal can be reached
within 30 steps. Otherwise, output ``-1'' for the dataset.
3618 - Cubic Eight-Puzzle 2/3
Sample Input
1 2
W W W
E W W
W W W
2 1
R B W
R W W
E W W
3 3
W B W
B R E
R B R
3 3
B W R
B W R
B E R
2 1
B B B
B R B
B R E
1 1
R R R
W W W
R R E
2 1
R R R
B W B
R R E
3 2
R R R
W E W
R R R
0 0
Sample Output
0
3
13
23
29
30
-1
-1
[/b]
解题报告
难度。。很大,BFS这个没有疑问,那么究竟是A*还是双广呢,由于本题的状态数很多,且转移方程很麻烦,所以首先考虑A*.
估价函数这里不在多说(其实是我忘了),但提交后TLE...,CODE如下
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <queue> #include <ctime> using namespace std; const int MaxHashSize = 1526597; const int MaxState = 2500000; int tot,target[256]; char g[9]; int dir[4][2] = {0,1,0,-1,-1,0,1,0}; int getdia[6][4] = {5,5,2,2,3,3,4,4,4,4,0,0,1,1,5,5,2,2,1,1,0,0,3,3}; typedef struct status { char pos; char step; int g; char h; friend bool operator < (const status& a ,const status& b) { if (a.step + a.h < b.step + b.h) return false; if (a.step + a.h == b.step + b.h && a.step < b.step) return false; return true; } }; priority_queue<status> q; status start; int Head[MaxHashSize],Next[MaxState]; status st[MaxState]; void init_Hash() { memset(Head,-1,sizeof(Head)); } int GetHashValue(status &x) { return x.g % MaxHashSize; } bool insert_Hash(int id) { int h = GetHashValue(st[id]); int u = Head[h]; while(u != -1) { if (st[u].g == st[id].g) return false; u = Next[u]; } Next[id] = Head[h]; Head[h] = id; return true; } int caculateh(status &x) { int res = 0; int ok = 1; for(int i = 0 ; i < 9 ; ++ i) { int temp = 0; for(int j = 0 ; j < 3 ; ++ j) { int s = (x.g >> (3*i + j)) & 1; temp |= (s << j); } if ( (temp == 0 || temp == 1) && g[i] != 'W') res ++ ; else if ( (temp == 2 || temp == 3) && g[i] !='R') res ++; else if ( (temp == 4 || temp == 5) && g[i] != 'B') res ++; else if (temp == 7 && g[i] != 'E' ) { res ++; ok = 0; } } if (ok) return res; else return res - 1; } int bfs() { int front = 0 ,rear = 1; q.push(start); while(!q.empty()) { status ss = q.top();q.pop(); st[front++] = ss; if (ss.h == 0) return ss.step; if (ss.h + ss.step > 30) return -1; int pos = ss.pos; int x = pos / 3; int y = pos % 3; int step = ss.step; int g = ss.g; for(int i = 0 ; i < 4 ; ++ i) { int newx = x + dir[i][0]; int newy = y + dir[i][1]; if (newx >= 3 || newx < 0 || newy >= 3 || newy < 0) continue; int newpos = newx * 3 + newy; status ns = ss; int temp = 0; for(int j = 0 ; j < 3 ; ++ j) { int s = (g >> (newpos * 3 + j) ) & 1; temp |= (s << j); } int sis = getdia[temp][i]; for(int j = 0 ; j < 3 ;++ j) ns.g |= (1 << (newpos*3 + j)); for(int j = 0 ; j < 3 ; ++ j) if (sis >> j & 1) ns.g |= (1 << pos * 3 + j); else ns.g &= ~(1 << pos * 3 + j); ns.step = step + 1; ns.pos = newpos; ns.h = caculateh(ns); st[rear] = ns; if (insert_Hash(rear)) { q.push(ns); rear++; } } } return -1; } int main(int argc, char * argv[]) { int kk = clock(); int s1,s2; while(scanf("%d%d%*c",&s1,&s2) && s1) { tot = 0; for(int i = 0 ; i < 9 ; ++ i) scanf("%c%*c",&g[i]); int fp = (s2-1) * 3 + s1 - 1; start.pos = fp; start.g = 0; init_Hash(); for(int i = 0 ; i < 3 ; ++ i) start.g |= (1 << (3*fp+i)); st[0] = start; insert_Hash(0); start.h = caculateh(start); start.step = 0; while(!q.empty()) q.pop(); cout << bfs() << endl; } cout << "Time use " << clock() - kk << endl; return 0; }
这里的代码中有Clock(),大家可以试试几组数据,30步的极限或者-1,速度非常慢。。(无法忍受)
那么,我们只能改用双广了,因为末状态有256种,所以我们用一个dfs把末状态压进去,提交后AC~
顺便多题一句双广复杂度是 2*n^(a/2) ,而单向的是n^a,code 如下
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> using namespace std; const int MaxHashSize = 1526597; const int MaxState = 2500000; int tot,target[256],ssl; char g[9]; int dir[4][2] = {0,1,0,-1,-1,0,1,0}; int getdia[6][4] = {5,5,2,2,3,3,4,4,4,4,0,0,1,1,5,5,2,2,1,1,0,0,3,3}; typedef struct status { char pos; char step; int g; }; status start; int Head[MaxHashSize],Next[MaxState]; int Head2[MaxHashSize],Next2[MaxState]; status st[MaxState]; status st2[MaxState]; void init_Hash() { memset(Head,-1,sizeof(Head)); memset(Head2,-1,sizeof(Head)); } int GetHashValue(status &x) { return x.g % MaxHashSize; } bool insert_Hash(int id ,int l) { int h; if (l == 0) h = GetHashValue(st[id]); else h = GetHashValue(st2[id]); int u; if (l == 0) u = Head[h]; else u = Head2[h]; while(u != -1) { if (l == 0) { if (st[u].g == st[id].g) return false; u = Next[u]; } else { if (st2[u].g == st2[id].g) return false; u = Next2[u]; } } if (l == 0) { Next[id] = Head[h]; Head[h] = id; } else { Next2[id] = Head2[h]; Head2[h] = id; } return true; } int meet(int id,int l) { int u,h; if (l == 0) { h = GetHashValue(st[id]); int u = Head2[h]; while(u != -1) { if (st2[u].g == st[id].g) return st[id].step + st2[u].step; u = Next2[u]; } return -1; } else { h = GetHashValue(st2[id]); int u = Head[h]; while(u != -1) { if (st[u].g == st2[id].g) return st[u].step + st2[id].step; u = Next[u]; } return -1; } } int bfs() { int front = 0 ,rear = 1; int front2 = 0 , rear2 = 256; while(front < rear && front2 < rear2) { if (1) { status ss = st[front++] ; int ans = meet(front-1,0); if (ans != -1) return ans > 30 ? -1 : ans; if (ss.step >= 30) return -1; int pos = ss.pos; int x = pos / 3; int y = pos % 3; int step = ss.step; int g = ss.g; for(int i = 0 ; i < 4 ; ++ i) { int newx = x + dir[i][0]; int newy = y + dir[i][1]; if (newx >= 3 || newx < 0 || newy >= 3 || newy < 0) continue; int newpos = newx * 3 + newy; status ns = ss; int temp = 0; for(int j = 0 ; j < 3 ; ++ j) { int s = (g >> (newpos * 3 + j) ) & 1; temp |= (s << j); } int sis = getdia[temp][i]; for(int j = 0 ; j < 3 ;++ j) ns.g |= (1 << (newpos*3 + j)); for(int j = 0 ; j < 3 ; ++ j) if (sis >> j & 1) ns.g |= (1 << pos * 3 + j); else ns.g &= ~(1 << pos * 3 + j); ns.step = step + 1; ns.pos = newpos; st[rear] = ns; if (insert_Hash(rear,0)) { rear++; } } } status ss = st2[front2++] ; int ans = meet(front2-1,1); if (ans != -1) return ans > 30 ? -1 : ans; if (ss.step >= 30) return -1; int pos = ss.pos; int x = pos / 3; int y = pos % 3; int step = ss.step; int g = ss.g; for(int i = 0 ; i < 4 ; ++ i) { int newx = x + dir[i][0]; int newy = y + dir[i][1]; if (newx >= 3 || newx < 0 || newy >= 3 || newy < 0) continue; int newpos = newx * 3 + newy; status ns = ss; int temp = 0; for(int j = 0 ; j < 3 ; ++ j) { int s = (g >> (newpos * 3 + j) ) & 1; temp |= (s << j); } int sis = getdia[temp][i]; for(int j = 0 ; j < 3 ;++ j) ns.g |= (1 << (newpos*3 + j)); for(int j = 0 ; j < 3 ; ++ j) if (sis >> j & 1) ns.g |= (1 << pos * 3 + j); else ns.g &= ~(1 << pos * 3 + j); ns.step = step + 1; ns.pos = newpos; st2[rear2] = ns; if (insert_Hash(rear2,1)) { rear2++; } } } return -1; } void dfs(int n,int temp) { if (n == 9) { st2[tot].g = temp; st2[tot].step = 0; insert_Hash(tot,1); st2[tot++].pos = ssl; } else { int f; if (g == 'W') { f = temp; dfs(n+1,f); f |= (1 << (3*n)); dfs(n+1,f); } else if(g == 'R') { f = temp; f |= (1 << (3*n+1)); dfs(n+1,f); f |= (1 << 3*n); dfs(n+1,f); } else if(g == 'B') { f = temp; f |= (1 << 3*n+2); dfs(n+1,f); f |= (1 << 3*n); dfs(n+1,f); } else if(g == 'E') { f = temp; for(int j = 0 ; j < 3 ; ++ j) f |= (1 << 3*n + j); dfs(n+1,f); } } } int main(int argc, char * argv[]) { int s1,s2; while(scanf("%d%d%*c",&s1,&s2) && s1) { tot = 0; for(int i = 0 ; i < 9 ; ++ i) { scanf("%c%*c",&g[i]); if (g[i] == 'E') ssl = i; } int fp = (s2-1) * 3 + s1 - 1; start.pos = fp; start.g = 0; init_Hash(); dfs(0,0); for(int i = 0 ; i < 3 ; ++ i) start.g |= (1 << (3*fp+i)); st[0] = start; insert_Hash(0,0); start.step = 0; cout << bfs() << endl; } return 0; }
相关文章推荐
- UVA-1604 Cubic Eight-Puzzle (双向BFS+状态压缩+限制搜索层数)
- 【习题 7-9 UVA-1604】Cubic Eight-Puzzle
- UVA 1604:Cubic Eight-Puzzle(模拟,BFS Grade C)
- 1604 - Cubic Eight-Puzzle
- Cubic Eight-Puzzle UVA - 1604
- 搜索 POJ 3131 Cubic Eight-Puzzle
- POJ 3131 Cubic Eight-Puzzle
- LA 3618 Cubic Eight-Puzzle
- UVALIVE 6301 The Shortcut Eight-Puzzle
- POJ-3131-Cubic Eight-Puzzle(双向BFS+哈希)
- poj 3131 Cubic Eight-Puzzle 双向广搜 Hash判重
- Eight queens puzzle——八皇后问题
- UVa 227 - Puzzle
- UVa227 Puzzle
- uva 227 Puzzle
- hdu 2541 Another Eight Puzzle(dfs)
- Puzzle UVA - 227
- UVa227 Puzzle
- UVA 519 Puzzle (II) (dfs + 剪枝)
- UVA227-Puzzle