题意:
有一个5*5的01阵,有一个位子是空用*表示。每个0或1都可以走马步到空格子。
现在给一个初始的矩阵,要变成下面这个状态。
11111
01111
00*11
00001
00000
问最少的步数。若超过15步则输出-1.
做法:
一开始打了一个状压bfs。然后光荣地没跑过样例= =
正解是A*。观察到有一个条件叫做超过15步就输出-1,于是我们可以1~15枚举步数,这样限定了dfs的深度,最多dfs15层,就会快很多。
另外加一些小优化,比如当前步数加上还需走的步数超过枚举的k的话就不用再继续走了(肯定不优)。
代码:
/*************************************************************
Problem: bzoj 1085 [SCOI2005]骑士精神
User: fengyuan
Language: C++
Result: Accepted
Time: 552 ms
Memory: 1292 kb
Submit_Time: 2018-01-17 13:19:48
*************************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<map>
#include<queue>
#define id(x, y) (((x)-1)*5+(y))
using namespace std;
typedef long long ll;
const int N = 7;
const int dx[8] = {-2, -2, -1, 1, 2, 2, 1, -1};
const int dy[8] = {-1, 1, 2, 2, 1, -1, -2, -2};
const int b[6][6] = {
{0, 0, 0, 0, 0, 0},
{0, 1, 1, 1, 1, 1},
{0, 0, 1, 1, 1, 1},
{0, 0, 0, 2, 1, 1},
{0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 0}
};
char s[10];
int a[N][N], k, sx, sy;
bool flg;
struct node{
ll sta; int step;
node() {}
node(ll x, int y) { sta = x, step = y; }
};
inline bool ok(int x, int y) { return x >= 1 && x <= 5 && y >= 1 && y <= 5; }
inline bool check(int a[7][7])
{
for(int i = 1; i <= 5; i ++)
for(int j = 1; j <= 5; j ++) if(a[i][j] != b[i][j]) return 0;
return 1;
}
inline int cal(int a[7][7])
{
int ret = 0;
for(int i = 1; i <= 5; i ++)
for(int j = 1; j <= 5; j ++) ret += a[i][j] != b[i][j];
return ret;
}
inline void dfs(int step, int a[7][7], int x, int y)
{
if(step == k) { if(check(a)) flg = 1; return; }
if(flg) return;
for(int i = 0; i < 8; i ++) {
int xx = x+dx[i], yy = y+dy[i];
if(!ok(xx, yy)) continue;
swap(a[xx][yy], a[x][y]);
if(cal(a) + step <= k) dfs(step+1, a, xx, yy);
swap(a[xx][yy], a[x][y]);
}
}
int main()
{
int test; scanf("%d", &test);
while(test --) {
for(int i = 1; i <= 5; i ++) {
scanf("%s", s+1);
for(int j = 1; j <= 5; j ++) {
a[i][j] = s[j]-'0';
if(s[j] == '*') a[i][j] = 2, sx = i, sy = j;
}
}
flg = 0;
for(k = 1; k <= 15; k ++) {
dfs(0, a, sx, sy);
if(flg) { printf("%d\n", k); break; }
}
if(!flg) puts("-1");
}
return 0;
}