UVa 10181 15Puzzle Problem

题目链接不好找:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1122

用的 IDA*,跑了6.536s,时限是45s(刚看了627个人通过,我是第515名……,排行榜比较恐怖啊,见下图)

这道题的逆序剪枝和八数码不同,具体参考这篇文章:http://mathworld.wolfram.com/15Puzzle.html
1A!

  1 # include <stdio.h>
  2 # include <math.h>
  3 # include <string.h>
  4 
  5 # define MIN(x, y) ((x)<(y) ? (x):(y))
  6 
  7 # define SIZE 4
  8 # define N SIZE*SIZE
  9 # define DIR_N 4
 10 # define INF 0x7fffffff
 11 # define MAX_DEPTH 1000
 12 
 13 char solved;
 14 char start[N], goal[N];
 15 char cur[N];
 16 
 17 int bound;
 18 const char md[] = {'U', 'L', 'R', 'D'};
 19 const short int dir[][2] = {{-1,0}, {0,-1}, {0,1}, {1,0}};
 20 char path[MAX_DEPTH];
 21 
 22 void solve(void);
 23 void read(char *s);
 24 int IDAstar(void);
 25 char inv_judge(char *s);
 26 int heu(void);
 27 int dfs(int zero_pos, int depth, char direction);
 28 
 29 int main()
 30 {
 31     int i, T;
 32         
 33     scanf("%d", &T);
 34     for (i = 0; i < N-1; ++i)
 35         goal[i] = i + 1;
 36     goal[N-1] = 0;
 37     for (i = 1; i <= T; ++i)
 38     {
 39         read(start);
 40         memcpy(cur, start, N);
 41         solve();
 42     }
 43     
 44     return 0;
 45 }
 46 
 47 void solve()
 48 {
 49     int i, depth;
 50 
 51     if (inv_judge(start)) puts("This puzzle is not solvable.");
 52     else
 53     {
 54         memset(path, -1, sizeof(path));
 55         depth = IDAstar();
 56         for (i = 0; path[i]!=-1; ++i)
 57         {
 58             putchar(md[path[i]]);
 59         }
 60         putchar('\n');
 61     }
 62 }
 63 
 64 void read(char *s)
 65 {
 66     int i, t;
 67 
 68     for (i = 0; i < N; ++i)
 69     {
 70         scanf("%d", &t);
 71         s[i] = t;
 72     }
 73 }
 74 
 75 int IDAstar(void)
 76 {
 77     int i;
 78 
 79     solved = 0;
 80     bound = heu();
 81 
 82     for (i = 0; start[i] && i < N; ++i) ;
 83 
 84     while (!solved && bound<100)
 85     {
 86         bound = dfs(i, 0, -10);
 87     }
 88 
 89     return bound;
 90 }
 91 
 92 int dfs(int pos, int depth, char d)
 93 {
 94     int h, i, nx, ny, npos, nbound, t;
 95 
 96     h = heu();
 97 
 98     if (depth+h > bound) return depth+h;
 99     if (h == 0)
100     {
101         solved = 1;
102         return depth;
103     }
104 
105     nbound = INF;
106     for (i = 0; i < DIR_N; ++i)
107     {
108         if (i+d == DIR_N-1) continue;
109         nx = pos/SIZE + dir[i][0];
110         ny = pos%SIZE + dir[i][1];
111         if (0<=nx && nx<SIZE && 0<=ny && ny<SIZE)
112         {
113             path[depth] = i;
114             npos = nx*SIZE + ny;
115             cur[pos] = cur[npos]; cur[npos] = 0;     /* pos -> npos */
116             t = dfs(npos, depth+1, i);
117             if (solved) return t;
118             nbound = MIN(nbound, t);
119             cur[npos] = cur[pos]; cur[pos] = 0;
120         }
121     }
122     return nbound;
123 }
124 
125 int heu(void)            /* return heu(cur_state) */
126 {
127     char ch;
128     int i, j, ret;
129 
130     ret = 0;
131     for (i = 0; i < N; ++i)
132     {
133         ch = goal[i];
134         if (ch == 0) continue;
135         for (j = 0; j < N; ++j)
136         {
137             if (ch == cur[j])
138             {
139                 ret = ret + abs(i/SIZE-j/SIZE) + abs(i%SIZE-j%SIZE);
140             }
141         }
142     }
143 
144     return ret;
145 }
146 
147 char inv_judge(char *s)
148 {
149     char ch, ret;
150     int i, j;
151 
152     ret = 0;
153     for (i = 0; i < N-1; ++i)
154     {
155         if ((ch = s[i]) == 0 && (i/SIZE+1)&0x1)
156             ret = 1 - ret;
157         for (j = i+1; j < N; ++j)
158         {
159             if (s[j] && s[j]<ch) ret = 1 - ret;
160         }
161     }
162 
163     return ret;
164 }

//

原文地址:https://www.cnblogs.com/JMDWQ/p/2520001.html