LightOJ 1139 8 puzzle + hdu 1043 Eight A*

 

这两道做时都是超时,无奈之下学习了一下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[] = { 112624120720504040320362880 };
 8 int visit[363000], parent[363000], d[363000],
 9 dir[4][2] = {{-1,0}, {1,0}, {0,-1}, {01}}; // 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] == 9continue;
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] == 9continue;
45         for(j = i+1; j < n; ++j)
46             if(s[i] > s[j]) ++t;
47     }
48     if(t&1return true;
49     return false;
50 }
51 
52 void bfs(){ //优先队列+广搜
53     node n1, n2; int i, x, y;
54     memset(visit, falsesizeof(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 }
View Code

 

 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[] = { 112624120720504040320362880 };
  9 int visit[363000], parent[363000], d[363000],
 10 dir[4][2] = {-10100, -101}; // 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] == 9continue;
 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 = 0string 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] == 9continue;
 60         for(j = i+1; j < n; ++j)
 61             if(s[i] > s[j]) ++t;
 62     }
 63     if(t&1return true;
 64     return false;
 65 }
 66 
 67 void bfs(){ //优先队列+广搜
 68     node n1, n2; int i, x, y;
 69     memset(visit, falsesizeof(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 }
View Code

 

 

 

 

posted @ 2013-08-07 10:39  YaLing  阅读(477)  评论(0编辑  收藏  举报