POJ1077 Eight —— IDA*算法

主页面:http://www.cnblogs.com/DOLFAMINGO/p/7538588.html



代码一:像BFS那样,把棋盘数组放在结构体中。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 #define ms(a,b) memset((a),(b),sizeof((a)))
 13 using namespace std;
 14 typedef long long LL;
 15 const int INF = 2e9;
 16 const LL LNF = 9e18;
 17 const int MOD = 1e9+7;
 18 const int MAXN = 1e6+10;
 19 #define AIM  1     //123456789的哈希值为1
 20 
 21 struct node
 22 {
 23     int s[9];
 24     int loc;
 25 };
 26 
 27 int fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
 28 int dir[4][2] = { -1,0, 1,0, 0,-1, 0,1 };
 29 char op[4] = {'u', 'd', 'l', 'r'  };
 30 
 31 int cantor(int s[])  //获得哈希函数值
 32 {
 33     int sum = 0;
 34     for(int i = 0; i<9; i++)
 35     {
 36         int num = 0;
 37         for(int j = i+1; j<9; j++)
 38             if(s[j]<s[i]) num++;
 39         sum += num*fac[8-i];
 40     }
 41     return sum+1;
 42 }
 43 
 44 int dis_h(int s[])  //获得曼哈顿距离
 45 {
 46     int dis = 0;
 47     for(int i = 0; i<9; i++)
 48     if(s[i]!=9)
 49     {
 50         int x = i/3, y = i%3;
 51         int xx = (s[i]-1)/3, yy = (s[i]-1)%3;
 52         dis += abs(x-xx) + abs(y-yy);
 53     }
 54     return dis;
 55 }
 56 
 57 char path[100];
 58 bool IDAstar(node now, int depth, int pre, int limit)
 59 {
 60     if(dis_h(now.s)==0)     //搜到123456789
 61     {
 62         path[depth] = '\0';
 63         puts(path);
 64         return true;
 65     }
 66 
 67     int x = now.loc/3;
 68     int y = now.loc%3;
 69     for(int i = 0; i<4; i++)
 70     {
 71         if(i+pre==1 || i+pre==5) continue;  //方向与上一步相反, 剪枝
 72         int xx = x + dir[i][0];
 73         int yy = y + dir[i][1];
 74         if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
 75         {
 76             node tmp = now;
 77             tmp.s[x*3+y] = tmp.s[xx*3+yy];
 78             tmp.s[xx*3+yy] = 9;
 79             tmp.loc = xx*3+yy;
 80             path[depth] = op[i];
 81             if(depth+1+dis_h(tmp.s)<=limit)     //在限制内
 82                 if(IDAstar(tmp, depth+1, i, limit))
 83                     return true;
 84         }
 85     }
 86     return false;
 87 }
 88 
 89 int main()
 90 {
 91     char str[50];
 92     while(gets(str))
 93     {
 94         node now;
 95         int cnt = 0;
 96         for(int i = 0; str[i]; i++)
 97         {
 98             if(str[i]==' ') continue;
 99             if(str[i]=='x') now.s[cnt] = 9, now.loc = cnt++;
100             else  now.s[cnt++] = str[i]-'0';
101         }
102 
103         int limit;
104         for(limit = 0; limit<=100; limit++)     //迭代加深搜
105             if(IDAstar(now, 0, INF, limit))
106                 break;
107         if(limit>100)
108             puts("unsolvable");
109     }
110 }
View Code

 

代码二:根据DFS的特点,由于棋盘每次只交换一对,所以可以只开一个棋盘数组。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 #define ms(a,b) memset((a),(b),sizeof((a)))
 13 using namespace std;
 14 typedef long long LL;
 15 const int INF = 2e9;
 16 const LL LNF = 9e18;
 17 const int MOD = 1e9+7;
 18 const int MAXN = 1e6+10;
 19 
 20 
 21 int M[100];
 22 int fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
 23 int dir[4][2] = { -1,0, 1,0, 0,-1, 0,1 };
 24 char op[4] = {'u', 'd', 'l', 'r'  };
 25 
 26 int cantor(int s[])  //获得哈希函数值
 27 {
 28     int sum = 0;
 29     for(int i = 0; i<9; i++)
 30     {
 31         int num = 0;
 32         for(int j = i+1; j<9; j++)
 33             if(s[j]<s[i]) num++;
 34         sum += num*fac[8-i];
 35     }
 36     return sum+1;
 37 }
 38 
 39 int dis_h(int s[])  //获得曼哈顿距离
 40 {
 41     int dis = 0;
 42     for(int i = 0; i<9; i++)
 43     if(s[i]!=9)
 44     {
 45         int x = i/3, y = i%3;
 46         int xx = (s[i]-1)/3, yy = (s[i]-1)%3;
 47         dis += abs(x-xx) + abs(y-yy);
 48     }
 49     return dis;
 50 }
 51 
 52 char path[100];
 53 bool IDAstar(int loc, int depth, int pre, int limit)
 54 {
 55     int h = dis_h(M);
 56     if(depth+h>limit)
 57         return false;
 58 
 59     if(h==0)     //搜到123456789
 60     {
 61         path[depth] = '\0';
 62         puts(path);
 63         return true;
 64     }
 65 
 66     int x = loc/3;
 67     int y = loc%3;
 68     for(int i = 0; i<4; i++)
 69     {
 70         if(i+pre==1 || i+pre==5) continue;  //方向与上一步相反, 剪枝
 71         int xx = x + dir[i][0];
 72         int yy = y + dir[i][1];
 73         if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
 74         {
 75             swap(M[loc], M[xx*3+yy]);
 76             path[depth] = op[i];
 77             if(IDAstar(xx*3+yy, depth+1, i, limit))
 78                 return true;
 79             swap(M[loc], M[xx*3+yy]);
 80         }
 81     }
 82     return false;
 83 }
 84 
 85 int main()
 86 {
 87     char str[50];
 88     while(gets(str))
 89     {
 90         int cnt = 0, loc;
 91         for(int i = 0; str[i]; i++)
 92         {
 93             if(str[i]==' ') continue;
 94             if(str[i]=='x') M[cnt] = 9, loc = cnt++;
 95             else  M[cnt++] = str[i]-'0';
 96         }
 97 
 98         int limit;
 99         for(limit = 0; limit<=100; limit++)     //迭代加深搜
100             if(IDAstar(loc, 0, INF, limit))
101                 break;
102         if(limit>100)
103             puts("unsolvable");
104     }
105 }
View Code

 


 

posted on 2017-09-05 20:03  h_z_cong  阅读(275)  评论(0编辑  收藏  举报

导航