八数码(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 }

//

你可能感兴趣的:(a)