• 八数码(A*)


    第一道A*,照着A*的框架写的,不是很理解A*,写的也很长,中间有些标记的不太理解,去掉标记在POJ提交通过了,还是没理解A*的思想;

    犯了个低级错误:在判断新状态 0 的位置(nx, ny)是否越界时,应该是0 =< nx < 3,结果写成了0<= nx <=3,还叫LJ大牛一块查,最后终于给发现了;

    在写 A* 之前以为 A* 会省不少空间(扩展的节点相比 BFS 少很多),实际上却开了两个大数组: f[] 和 g[],一下子感觉也挺浪费的,时间上感觉快了很多,我测试的几组都是0MS,在POJ上提交是64MS;

    两周以前就决心花几天时间搞八数码和十五数码(主要是想学学A*),结果一下子就过了十几天,八数码的还是马马虎虎,十五数码目前只能寄希望与IDA*,还想想一下八数码的构造方法(感觉分治的思想可能会用上,虽然分治法行不通)。

      1 # include <cstdio>
      2 # include <queue>
      3 # include <cstring>
      4 # include <cmath>
      5 /*# include <ctime>  */
      6 
      7 # define N 9
      8 
      9 using namespace std;
     10 
     11 typedef struct state
     12 {
     13     char a[N];
     14     unsigned short h; 
     15     unsigned int c;
     16 } state;
     17 
     18 typedef struct 
     19 {
     20     int p;
     21     char d;
     22 }path;
     23 
     24 path p[362885];
     25 
     26 const char md[] = {'u', 'd', 'l', 'r'};
     27 const short int dir[][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}};
     28 const int fact[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
     29 
     30 unsigned short int g[362885];
     31 unsigned short int f[362885];
     32 
     33 struct cmp{
     34     bool operator()(state s1, state s2){
     35         return f[s1.c] > f[s2.c];
     36     }
     37 };
     38 
     39 priority_queue<state, vector<state>, cmp> Q;
     40 
     41 int cantor(state s)
     42 {
     43     char ch;
     44     int i, j, c, ret;
     45     
     46     ret = 0;
     47     for (i = 0; i < N-1; ++i)
     48     {
     49         c = 0;
     50         ch = s.a[i];
     51         for (j = i+1; j < N; ++j)
     52             if (s.a[j] < ch) ++c;
     53         ret += c*fact[8-i];
     54     }
     55     
     56     return ret;
     57 }    
     58 
     59 void set_goal(char *s, state *goal)
     60 {
     61     int i;
     62     
     63     for (i = 0; i < N; ++i)
     64         (*goal).a[i] = s[i] - '0';
     65 }
     66 
     67 char bool_inv(state s)
     68 {
     69     char ch, ret;
     70     int i, j;
     71     
     72     ret = 0;
     73     for (i = 0; i < N-1; ++i)
     74     {
     75         if ((ch = s.a[i]) == 0) continue;
     76         for (j = i+1; j < N; ++j)
     77             if (s.a[j] && s.a[j] < ch) ret = 1 - ret;
     78     }
     79     
     80     return ret;
     81 }
     82 
     83 
     84 int heu(state cur, state goal)                     /* Manhattan 距离, 不含 0 */
     85 {
     86     char ch;
     87     int i, j, ret;
     88     
     89     ret = 0;
     90     for (i = 0; i < N; ++i)
     91     {
     92         ch = goal.a[i];
     93         //if (ch == 0) continue;
     94         for (j = 0; j < N; ++j)
     95         {
     96             if (cur.a[j] == ch)
     97             {
     98                 ret += abs(j/3 - i/3) + abs(j%3 - i%3);
     99                 break;
    100             }
    101         }
    102     }
    103     
    104     return ret;
    105 }
    106 
    107 int Astar(state start, state goal)
    108 {
    109     int cc, cn, cg;
    110     short int i, x, y, nx, ny;
    111     state cur, nst;
    112     
    113     memset(g, 0, sizeof(g));
    114     memset(f, 0, sizeof(f));
    115     memset(p, 0, sizeof(p));
    116    /* memset(vis, 0, sizeof(vis));  */
    117     
    118     while (!Q.empty()) Q.pop();
    119     
    120     g[start.c] = 1;                                               /* 用 g[] 代替 vis[] */
    121     f[start.c] = start.h + 1;
    122    /* vis[start.c] = 1; */
    123     Q.push(start);
    124     
    125     while (!Q.empty())
    126     {
    127         cur = Q.top();
    128         Q.pop();
    129         /* vis[cur.c] = 2; */
    130         if (cur.c == goal.c) {return g[cur.c]-1;}                        /* 搜索到目标节点, 走的距离应为 g[]-1 */
    131         for (i = 0; cur.a[i] && i < N; ++i) ;
    132         x = i / 3; y = i % 3;
    133         for (i = 0; i < 4; ++i)
    134         {
    135             nx = x + dir[i][0]; ny = y + dir[i][1];
    136             if (0<=nx && nx<3 && 0<=ny && ny<3)                 /* 这里边界判断原来写成了<=3,结果差得很远 */
    137             {
    138                 nst = cur;
    139                 nst.a[x*3+y] = cur.a[nx*3+ny];
    140                 nst.a[nx*3+ny] = 0;
    141                 nst.c = cantor(nst);
    142                 if (g[nst.c] == 0)
    143                 {
    144                     p[nst.c].p = cur.c;
    145                     p[nst.c].d = md[i];
    146                     nst.h = heu(nst, goal);
    147                     g[nst.c] = g[cur.c] + 1;
    148                     f[nst.c] = g[nst.c] + nst.h;
    149                     Q.push(nst);
    150       /*              vis[nst.c] = 1;  */
    151                 }
    152                 /*
    153                 else if (vis[nst.c] == 1 && g[nst.c] > g[cur.c]+1)
    154                 {
    155                     p[nst.c].p = cur.c;
    156                     p[nst.c].d = md[i];
    157                     g[nst.c] = g[cur.c] + 1;
    158                     f[nst.c] = g[nst.c] + nst.h;
    159                     //Q.push(nst);
    160                 }
    161                 */
    162             }
    163         }
    164     }
    165     
    166     return -1;
    167 }
    168 
    169 void print_path(int x)
    170 {
    171     if (p[x].p == 0) return ;
    172     print_path(p[x].p);
    173     putchar(p[x].d);
    174 }
    175 
    176 bool read(state* s)
    177 {
    178     int i;
    179     char c[5];
    180     
    181     if (EOF == scanf("%s", c)) return false;
    182     else (*s).a[0] = (c[0]=='x' ? 0:c[0]-'0'); 
    183     for (i = 1; i < N; ++i)
    184     {
    185         scanf("%s", c);
    186         (*s).a[i] = (c[0]=='x' ? 0:c[0]-'0');
    187     }
    188     (*s).c = cantor(*s);
    189 
    190     return true;
    191 }
    192 
    193 void solve(state start, state goal)
    194 {
    195     start.h = heu(start, goal);
    196     if (bool_inv(start) != bool_inv(goal)) puts("unsolvable");
    197     else
    198     {
    199         Astar(start, goal);                      /* 逆序剪枝后,剩下的状态一定有解 */
    200         print_path(goal.c);
    201         putchar('\n');
    202     }
    203 }    
    204 
    205 int main() 
    206 {
    207     state start, goal;
    208     
    209     freopen("in.txt", "r", stdin);
    210     freopen("out.txt", "w", stdout);
    211 
    212     // set_goal("123456780", &goal);
    213     goal.c = cantor(goal);
    214     while (read(&start))
    215     {
    216         read(&goal);
    217         solve(start, goal);
    218     }    
    219     
    220    /* printf("time cost %u ms.\n", clock()/CLOCKS_PER_SEC);  */
    221      
    222     return 0;
    223 }

    //

  • 相关阅读:
    Python 学习目录
    Django目录
    SQLAlchemy
    Flask之Sqlalchemy
    Websocket
    Mongodb
    虚拟环境
    Github
    LINUX
    内存管理和垃圾回收机制
  • 原文地址:https://www.cnblogs.com/JMDWQ/p/2517321.html
Copyright © 2020-2023  润新知