IDA*的第一道题,移动棋子太麻烦啦,所以移动空格。
因为题目只求15步以内能否到达,所以枚举1-15为步数,然后每次A*的方式估价一下,f=g+h,h为当前状态到目标状态期望步数,g为已经走的步数,f如果超过当次枚举的步数就可以直接返回。
然后可以优化一下,不走回头路。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned long long ull; 5 const int maxn = 5e5 + 110; 6 const int inf = 1e9; 7 int n, m, t, mp[7][7], f; 8 int dx[8] = { -2,-2,-1,1,-1,1,2,2 }; 9 int dy[8] = { -1,1,2, 2,-2,-2,-1,1 }; 10 const int p[7][7] = { 11 {1,1,1,1,1}, 12 {0,1,1,1,1}, 13 {0,0,-1,1,1}, 14 {0,0,0,0,1}, 15 {0,0,0,0,0} 16 }; 17 inline int h() { 18 int sum = 0; 19 for (int i = 0; i < 5; i++) 20 for (int j = 0; j < 5; j++) 21 if (mp[i][j] != p[i][j])sum++; 22 return sum; 23 } 24 inline int check(int x, int y) { 25 if (x >= 0 && x < 5 && y >= 0 && y < 5)return 1; 26 return 0; 27 } 28 inline void dfs(int d, int x, int y, int maxd, int fa) { 29 if (d == maxd) { 30 if (!h()) 31 f = 1; 32 return; 33 } 34 for (int i = 0; i < 8 && f == 0; i++) { 35 if (i == 7 - fa)continue; 36 int xx = x + dx[i]; 37 int yy = y + dy[i]; 38 if (!check(xx, yy))continue; 39 swap(mp[x][y], mp[xx][yy]); 40 if (h() + d <= maxd) 41 dfs(d + 1, xx, yy, maxd, i); 42 swap(mp[x][y], mp[xx][yy]); 43 } 44 } 45 char s[10]; 46 int main() { 47 int t; 48 scanf("%d", &t); 49 while (t--) { 50 int sx, sy; 51 f = 0; 52 for (int i = 0; i < 5; i++) { 53 scanf("%s", s); 54 for (int j = 0; j < 5; j++) { 55 if (s[j] == '*')mp[i][j] = -1, sx = i, sy = j; 56 else mp[i][j] = s[j] - '0'; 57 } 58 } 59 if (!h()) { 60 printf("0\n"); 61 continue; 62 } 63 for (int i = 1; i <= 15; i++) { 64 dfs(0, sx, sy, i, inf); 65 if (f) { 66 printf("%d\n", i); 67 break; 68 } 69 } 70 if (f == 0) 71 printf("-1\n"); 72 } 73 }