-------------------------------------------------------------------------------------------------------------------------------
在搜索的时候可以加一个有效的剪枝:先bfs预处理出每个空格移到边缘所需的最少步数,这样如果在搜索过程中发现某个空格即便按最快的方案移动都不能在迭代加深限制的步数内到达边缘的话,就可以剪枝了。
#include
#include
#include
#include
#define MAXN 10
#define MAXD 40
#define INF 0x3f3f3f3f
int dx[] = { 0, -1, 1, 0 }, dy[] = { 1, 0, 0, -1 };
int N, M, g[MAXN][MAXN], ix[MAXD], iy[MAXD], dis[MAXN][MAXN];
int list[1010];
inline int inedge(int x, int y) {
return x == 1 || x == N || y == 1 || y == N;
}
int bfs(int sx, int sy) {
int i, x, y, nx, ny, d[MAXN][MAXN];
memset(d, -1, sizeof(d));
std::queue q;
d[sx][sy] = 0, q.push(sx * 10 + sy);
while (!q.empty()) {
x = q.front() / 10, y = q.front() % 10, q.pop();
if (inedge(x, y)) return d[x][y];
for (i = 0; i < 4; i++) {
nx = x + dx[i], ny = y + dy[i];
if (g[nx][ny] && d[nx][ny] == -1)
d[nx][ny] = d[x][y] + 1, q.push(nx * 10 + ny);
}
}
return 0;
}
void init() {
int i, j;
char b[MAXD];
for (i = 1; i <= N; i++) {
scanf("%s", b + 1);
for (j = 1; j <= N; j++) g[i][j] = 1 - (b[j] - '0'); // 将0、1反转。
}
M = 0;
for (i = 1; i <= N; i++)
for (j = 1; j <= N; j++) {
if (g[i][j]) {
if (inedge(i, j)) dis[i][j] = 0;
else {
dis[i][j] = bfs(i, j); // dis[i][j]表示这个点移动到边界的最小移动步数
ix[M] = i, iy[M] = j, ++M;//ix,iy数组记录需要移动的点。M表示需要移动的点的个数。
}
} else dis[i][j] = INF;
}
}
int Max(int *x, int *y) {
int i, ans = 0;
for (i = 0; i < M; i++) ans = std::max(ans, dis[x[i]][y[i]]);
return ans;
}
int dfs(int d, int *ix, int *iy) {
if (Max(ix, iy) > d) return 0; // 很重要的一步,剪枝。
if (d == 0) return 1;
int i, j, x[MAXD], y[MAXD], nx, ny;
for (i = 0; i < 4; i++) {
list[d] = i;
for (j = 0; j < M; j++) {
nx = ix[j] + dx[i], ny = iy[j] + dy[i]; //移动到新的点nx,ny。
if (inedge(ix[j], iy[j]) || g[nx][ny] == 0)
x[j] = ix[j], y[j] = iy[j];
else
x[j] = nx, y[j] = ny; //将移动到的新的点记录在x、y数组中。
}
if (dfs(d - 1, x, y)) return 1;
}
return 0;
}
void solve() {
int i, dep;
if (M == 0) return;
for (dep = 1; !dfs(dep, ix, iy); dep++);
for (i = dep; i > 0; i--) {
if (list[i] == 0) puts("east");
else if (list[i] == 1) puts("north");
else if (list[i] == 2) puts("south");
else puts("west");
}
}
int main() {
int t = 0;
while (scanf("%d", &N) == 1) {
init();
if (t++) printf("\n");
solve();
}
return 0;
}
参考:
本人博客:http://www.cnblogs.com/staginner/archive/2012/08/29/2662304.html
其它博客:http://www.cnblogs.com/staginner/archive/2012/08/29/2662304.html