这两道做时都是超时,无奈之下学习了一下A*算法,其实非常简单,就是加了一个获取当前状态到目的状态的长度(距离),很明显长度小的要排在前边,因此再加上优先队列
就形成了一个完美的组合,......AC代码......,还有一个IDA*算法,还要继续学习一下………
lightOJ 1139 8 puzzle
A* + hash + 优先队列广度搜索
1 #include <iostream>
2 #include <cstring>
3 #include <queue>
4 #include <cstdio>
5 using namespace std;
6
7 int s, maze[9], c[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
8 int visit[363000], parent[363000], d[363000],
9 dir[4][2] = {{-1,0}, {1,0}, {0,-1}, {0, 1}}; // u d l r
10
11
12 struct node{
13 int n[10]; //保存maze
14 int key, x; //maze对就的hash值和x所在的位置
15 int f, g; //估价值和移动的步数
16 bool operator < (const node& n) const{//当估价值相等时,步数小的先出队
17 return f > n.f || (f == n.f && g > n.g);
18 }
19 };
20
21 int cantor(int s[],int n){
22 int i, temp, num = 0;
23 for(i = 0; i < n; i++){
24 temp = 0;
25 for(int j = i + 1; j < n; j++)
26 if (s[j] < s[i]) temp++;
27 num += c[n-i-1] * temp;
28 }
29 return num;
30 }
31 int abs(int n) {return n > 0 ? n : (-n); }
32 int get_h(int s[], int n){ //获取估价值,就是到目的状态的距离
33 int sum = 0;
34 for(int i = 0; i < n; ++i){
35 if(s[i] == 9) continue;
36 sum += ( abs(i / 3 - (s[i] - 1) / 3) + abs(i % 3 - (s[i]-1) % 3) );
37 }
38 return sum;
39 }
40
41 bool f(int s[], int n){ //求逆序数,如果为奇数,则不能到目的状态
42 int i, j, t = 0;
43 for(i = 0; i < n - 1; ++i){
44 if(s[i] == 9) continue;
45 for(j = i+1; j < n; ++j)
46 if(s[i] > s[j]) ++t;
47 }
48 if(t&1) return true;
49 return false;
50 }
51
52 void bfs(){ //优先队列+广搜
53 node n1, n2; int i, x, y;
54 memset(visit, false, sizeof(visit));
55 for(i = 0; i < 9; ++i) n1.n[i] = maze[i]; n1.x = s; n1.key = cantor(n1.n, 9);
56 n1.g = 0; n1.f = get_h(n1.n, 9);
57 priority_queue<node> q; q.push(n1); visit[n1.key] = true; parent[n1.key] = -1;
58 if(n1.key == 0) {cout<<0<<endl; return;}
59 while(!q.empty()){
60 n1 = q.top(); q.pop();
61 x = n1.x / 3; y = n1.x % 3;
62 for(i = 0; i < 4; ++i){
63 n2 = n1;
64 int xx = x + dir[i][0], yy = y + dir[i][1];
65 if(xx >= 0 && yy >= 0 && xx <= 2 && yy <= 2){
66 n2.x = xx * 3 + yy;
67 swap(n2.n[n1.x], n2.n[n2.x]);
68 n2.key = cantor(n2.n, 9);
69 if(!visit[n2.key]){
70 n2.g++; n2.f = n2.g + get_h(n2.n, 9);
71 visit[n2.key] = true; d[n2.key] = i; parent[n2.key] = n1.key;
72 if(n2.key == 0) { cout<<n2.g<<endl; return; } q.push(n2);
73 }
74 }
75 }
76 }
77 // cout<<"impossible"<<endl;
78 }
79 int main(){
80 int t, i, cas; cin>>t;
81 for(cas = 1; cas <= t; ++cas){
82 cout<<"Case "<<cas<<": ";
83 for(i = 0; i < 9; ++i) {cin>>maze[i]; if(maze[i] == 0) { s = i; maze[i] = 9;} }
84 if(f(maze, 9)) cout<<"impossible"<<endl;
85 else bfs();
86 }
87 return 0;
88 }
2 #include <cstring>
3 #include <queue>
4 #include <cstdio>
5 using namespace std;
6
7 int s, maze[9], c[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
8 int visit[363000], parent[363000], d[363000],
9 dir[4][2] = {{-1,0}, {1,0}, {0,-1}, {0, 1}}; // u d l r
10
11
12 struct node{
13 int n[10]; //保存maze
14 int key, x; //maze对就的hash值和x所在的位置
15 int f, g; //估价值和移动的步数
16 bool operator < (const node& n) const{//当估价值相等时,步数小的先出队
17 return f > n.f || (f == n.f && g > n.g);
18 }
19 };
20
21 int cantor(int s[],int n){
22 int i, temp, num = 0;
23 for(i = 0; i < n; i++){
24 temp = 0;
25 for(int j = i + 1; j < n; j++)
26 if (s[j] < s[i]) temp++;
27 num += c[n-i-1] * temp;
28 }
29 return num;
30 }
31 int abs(int n) {return n > 0 ? n : (-n); }
32 int get_h(int s[], int n){ //获取估价值,就是到目的状态的距离
33 int sum = 0;
34 for(int i = 0; i < n; ++i){
35 if(s[i] == 9) continue;
36 sum += ( abs(i / 3 - (s[i] - 1) / 3) + abs(i % 3 - (s[i]-1) % 3) );
37 }
38 return sum;
39 }
40
41 bool f(int s[], int n){ //求逆序数,如果为奇数,则不能到目的状态
42 int i, j, t = 0;
43 for(i = 0; i < n - 1; ++i){
44 if(s[i] == 9) continue;
45 for(j = i+1; j < n; ++j)
46 if(s[i] > s[j]) ++t;
47 }
48 if(t&1) return true;
49 return false;
50 }
51
52 void bfs(){ //优先队列+广搜
53 node n1, n2; int i, x, y;
54 memset(visit, false, sizeof(visit));
55 for(i = 0; i < 9; ++i) n1.n[i] = maze[i]; n1.x = s; n1.key = cantor(n1.n, 9);
56 n1.g = 0; n1.f = get_h(n1.n, 9);
57 priority_queue<node> q; q.push(n1); visit[n1.key] = true; parent[n1.key] = -1;
58 if(n1.key == 0) {cout<<0<<endl; return;}
59 while(!q.empty()){
60 n1 = q.top(); q.pop();
61 x = n1.x / 3; y = n1.x % 3;
62 for(i = 0; i < 4; ++i){
63 n2 = n1;
64 int xx = x + dir[i][0], yy = y + dir[i][1];
65 if(xx >= 0 && yy >= 0 && xx <= 2 && yy <= 2){
66 n2.x = xx * 3 + yy;
67 swap(n2.n[n1.x], n2.n[n2.x]);
68 n2.key = cantor(n2.n, 9);
69 if(!visit[n2.key]){
70 n2.g++; n2.f = n2.g + get_h(n2.n, 9);
71 visit[n2.key] = true; d[n2.key] = i; parent[n2.key] = n1.key;
72 if(n2.key == 0) { cout<<n2.g<<endl; return; } q.push(n2);
73 }
74 }
75 }
76 }
77 // cout<<"impossible"<<endl;
78 }
79 int main(){
80 int t, i, cas; cin>>t;
81 for(cas = 1; cas <= t; ++cas){
82 cout<<"Case "<<cas<<": ";
83 for(i = 0; i < 9; ++i) {cin>>maze[i]; if(maze[i] == 0) { s = i; maze[i] = 9;} }
84 if(f(maze, 9)) cout<<"impossible"<<endl;
85 else bfs();
86 }
87 return 0;
88 }
hdu 1043 Eight
A* + hash + 优先队列广度搜索 + 记录路径 代码和上边的基本一致,只是稍微修改了一下
1 #include <iostream>
2 #include <cstring>
3 #include <queue>
4 #include <algorithm>
5 #include <cstdio>
6 using namespace std;
7
8 int s, maze[9], c[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
9 int visit[363000], parent[363000], d[363000],
10 dir[4][2] = {-1, 0, 1, 0, 0, -1, 0, 1}; // u d l r
11
12
13 struct node{
14 int n[10]; //保存maze
15 int key, x; //maze对就的hash值和x所在的位置
16 int f, g; //估价值和移动的步数
17 bool operator < (const node& n) const{
18 return f > n.f || (f == n.f && g > n.g);
19 }
20 };
21
22 int cantor(int s[],int n){ //康托展开,全排列,保存当前maze是哪个状态
23 int i, temp, num = 0;
24 for(i = 0; i < n; i++){
25 temp = 0;
26 for(int j = i + 1; j < n; j++)
27 if (s[j] < s[i]) temp++;
28 num += c[n-i-1] * temp;
29 }
30 return num;
31 }
32 int abs(int n) {return n > 0 ? n : (-n); }
33 int get_h(int s[], int n){ //获取估价值,就是到目的状态的距离
34 int sum = 0;
35 for(int i = 0; i < n; ++i){
36 if(s[i] == 9) continue;
37 sum += ( abs(i / 3 - (s[i] - 1) / 3) + abs(i % 3 - (s[i]-1) %
38
39 3) );
40 }
41 return sum;
42 }
43
44 void print_path(){ //打印路径
45 int i, t = 0; string path;
46 while(parent[t] != -1){
47 if(d[t] == 0) path += 'u';
48 else if(d[t] == 1) path += 'd';
49 else if(d[t] == 2) path += 'l';
50 else path += 'r';
51 t = parent[t];
52 }
53 for(i = path.length() - 1; i >= 0; --i) putchar(path[i]);
54 }
55
56 bool f(int s[], int n){ //求逆序数,如果为奇数,则不能到目的状态
57 int i, j, t = 0;
58 for(i = 0; i < n - 1; ++i){
59 if(s[i] == 9) continue;
60 for(j = i+1; j < n; ++j)
61 if(s[i] > s[j]) ++t;
62 }
63 if(t&1) return true;
64 return false;
65 }
66
67 void bfs(){ //优先队列+广搜
68 node n1, n2; int i, x, y;
69 memset(visit, false, sizeof(visit));
70 for(i = 0; i < 9; ++i) n1.n[i] = maze[i]; n1.x = s; n1.key = cantor
71
72 (n1.n, 9);
73 n1.g = 0; n1.f = get_h(n1.n, 9);
74 priority_queue<node> q; q.push(n1); visit[n1.key] = true; parent
75
76 [n1.key] = -1;
77 if(n1.key == 0) {return;}
78 while(!q.empty()){
79 n1 = q.top(); q.pop();
80 x = n1.x / 3; y = n1.x % 3;
81 for(i = 0; i < 4; ++i){
82 n2 = n1;
83 int xx = x + dir[i][0], yy = y + dir[i][1];
84 if(xx >= 0 && yy >= 0 && xx <= 2 && yy <= 2){
85 n2.x = xx * 3 + yy;
86 swap(n2.n[n1.x], n2.n[n2.x]);
87 n2.key = cantor(n2.n, 9);
88 if(!visit[n2.key]){
89 n2.g++; n2.f = n2.g + get_h(n2.n, 9);
90 visit[n2.key] = true; d[n2.key] = i; parent[n2.key]
91
92 = n1.key;
93 if(n2.key == 0) { print_path(); return; } q.push
94
95 (n2);
96 }
97 }
98 }
99 }
100 printf("unsolvable");
101 }
102
103 int main(){
104 char ss[100];
105 while(gets(ss)){
106 for(int i = 0, j = 0; ss[i]; ++i){
107 if(ss[i] == ' ') continue;
108 if(ss[i] == 'x') {maze[j++] = 9; s = j - 1;}
109 else if(ss[i] >= '0' && ss[i] <= '9') maze[j++] = ss[i] -
110
111 '0';
112 }
113 if(f(maze, 9)) puts("unsolvable");
114 else { bfs(); puts(""); }
115 }
116 return 0;
117 }
2 #include <cstring>
3 #include <queue>
4 #include <algorithm>
5 #include <cstdio>
6 using namespace std;
7
8 int s, maze[9], c[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
9 int visit[363000], parent[363000], d[363000],
10 dir[4][2] = {-1, 0, 1, 0, 0, -1, 0, 1}; // u d l r
11
12
13 struct node{
14 int n[10]; //保存maze
15 int key, x; //maze对就的hash值和x所在的位置
16 int f, g; //估价值和移动的步数
17 bool operator < (const node& n) const{
18 return f > n.f || (f == n.f && g > n.g);
19 }
20 };
21
22 int cantor(int s[],int n){ //康托展开,全排列,保存当前maze是哪个状态
23 int i, temp, num = 0;
24 for(i = 0; i < n; i++){
25 temp = 0;
26 for(int j = i + 1; j < n; j++)
27 if (s[j] < s[i]) temp++;
28 num += c[n-i-1] * temp;
29 }
30 return num;
31 }
32 int abs(int n) {return n > 0 ? n : (-n); }
33 int get_h(int s[], int n){ //获取估价值,就是到目的状态的距离
34 int sum = 0;
35 for(int i = 0; i < n; ++i){
36 if(s[i] == 9) continue;
37 sum += ( abs(i / 3 - (s[i] - 1) / 3) + abs(i % 3 - (s[i]-1) %
38
39 3) );
40 }
41 return sum;
42 }
43
44 void print_path(){ //打印路径
45 int i, t = 0; string path;
46 while(parent[t] != -1){
47 if(d[t] == 0) path += 'u';
48 else if(d[t] == 1) path += 'd';
49 else if(d[t] == 2) path += 'l';
50 else path += 'r';
51 t = parent[t];
52 }
53 for(i = path.length() - 1; i >= 0; --i) putchar(path[i]);
54 }
55
56 bool f(int s[], int n){ //求逆序数,如果为奇数,则不能到目的状态
57 int i, j, t = 0;
58 for(i = 0; i < n - 1; ++i){
59 if(s[i] == 9) continue;
60 for(j = i+1; j < n; ++j)
61 if(s[i] > s[j]) ++t;
62 }
63 if(t&1) return true;
64 return false;
65 }
66
67 void bfs(){ //优先队列+广搜
68 node n1, n2; int i, x, y;
69 memset(visit, false, sizeof(visit));
70 for(i = 0; i < 9; ++i) n1.n[i] = maze[i]; n1.x = s; n1.key = cantor
71
72 (n1.n, 9);
73 n1.g = 0; n1.f = get_h(n1.n, 9);
74 priority_queue<node> q; q.push(n1); visit[n1.key] = true; parent
75
76 [n1.key] = -1;
77 if(n1.key == 0) {return;}
78 while(!q.empty()){
79 n1 = q.top(); q.pop();
80 x = n1.x / 3; y = n1.x % 3;
81 for(i = 0; i < 4; ++i){
82 n2 = n1;
83 int xx = x + dir[i][0], yy = y + dir[i][1];
84 if(xx >= 0 && yy >= 0 && xx <= 2 && yy <= 2){
85 n2.x = xx * 3 + yy;
86 swap(n2.n[n1.x], n2.n[n2.x]);
87 n2.key = cantor(n2.n, 9);
88 if(!visit[n2.key]){
89 n2.g++; n2.f = n2.g + get_h(n2.n, 9);
90 visit[n2.key] = true; d[n2.key] = i; parent[n2.key]
91
92 = n1.key;
93 if(n2.key == 0) { print_path(); return; } q.push
94
95 (n2);
96 }
97 }
98 }
99 }
100 printf("unsolvable");
101 }
102
103 int main(){
104 char ss[100];
105 while(gets(ss)){
106 for(int i = 0, j = 0; ss[i]; ++i){
107 if(ss[i] == ' ') continue;
108 if(ss[i] == 'x') {maze[j++] = 9; s = j - 1;}
109 else if(ss[i] >= '0' && ss[i] <= '9') maze[j++] = ss[i] -
110
111 '0';
112 }
113 if(f(maze, 9)) puts("unsolvable");
114 else { bfs(); puts(""); }
115 }
116 return 0;
117 }