HDU 1010 Tempter of the Bone( DFS )

这道题有一个很重要的信息就是,走过的格子不能再走了,所以我觉得回溯+剪枝即可。

剪枝是很必要的,因为每个格子有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");
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值