这道题有一个很重要的信息就是,走过的格子不能再走了,所以我觉得回溯+剪枝即可。
剪枝是很必要的,因为每个格子有4个选择,那最差的情况下应该是4^49次幂吧......
剪枝有几点:
第一,就是计算一下最短路径,看在限制的的步数之内是否能走到
第二,就是超过k步的就返回
第三,如果已经找到了出口,就是退回
第四,很重要的是,在一个矩阵中,从一个点到另一个点,可能走的步数的奇偶性是一样的,如果从当前点到出口的步数的奇偶性与剩下的步数的奇偶性不同的话,那么那么就是肯定走不到的,需要剪枝的
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 10;
int n, m, t;
int sx, sy, ex, ey;
char g[N][N];
bool fid;
void dfs( int i, int j, int k ) {
//printf("%d %d %d\n", i, j, k);
if ( fid ) return;
if ( i == ex && j == ey && k == t ) { fid = true; return; }
if ( k >= t ) return;
int test = abs(i-ex) + abs(j-ey);
if ( test > t - k ) return;
if ( test % 2 != (t-k) % 2 ) return;
if ( i == ex && j == ey && k != t ) return;
int x[4] = { 0, 0, 1, -1 }, y[4] = { 1, -1, 0, 0 };
for ( int c = 0, a, b; c < 4; ++c ) {
a = i + x[c], b = j + y[c];
if ( g[a][b] == 'X' ) continue;
if ( g[a][b] == '.' || g[a][b] == 'D' ) {
char ch = g[a][b];
g[a][b] = 'X';
dfs( a, b, k+1 );
g[a][b] = ch;
}
}
}
int main()
{
while ( scanf("%d%d%d", &n, &m, &t) == 3 && ( n||m||t ) ) {
getchar();
for ( int i = 0; i <= m+1; ++i ) g[0][i] = g[n+1][i] = 'X';
for ( int i = 0; i <= n+1; ++i ) g[i][0] = g[i][m+1] = 'X';
for ( int i = 1; i <= n; ++i, getchar() )
for ( int j = 1; j <= m; ++j ) {
scanf("%c", &g[i][j]);
if ( g[i][j] == 'S' ) sx = i, sy = j;
if ( g[i][j] == 'D' ) ex = i, ey = j;
}
int test = abs(sx-ex) + abs(sy-ey);
if ( test > t ) {
printf("NO\n");
continue;
}
fid = false;
g[sx][sy] = 'X';
dfs( sx, sy, 0 );
if ( fid ) printf("YES\n");
else printf("NO\n");
}
}