题目链接:点击打开链接

最开始以为是在t秒内是否能到达door,写成了bfs,一直WA,后面发现是dfs后一直T...,在下实在不知道怎么剪枝了,就去百度了一发,然后发现了这个

 

int dis;                              
        dis=(T-time)-(fabs(x-xd)+fabs(y-yd));    // =剩下的时间-无障碍物下的最短路径 
        if(dis<0||dis%2)  return;                //小于0或为奇数就剪掉 

奇偶剪枝,出奇的好用,直接一发AC。至于原理嘛

 

 

 要从S走到D,忽略障碍显然最短路径长度是10,而我们把表格用1,0相间填满,易得无论怎么走,1->0或0->1一定是奇数步,0->0或1->1一定是偶数步。

假设还剩13秒,我们先走掉最短路径的10秒,到达的地方一定是0,再走剩下的3秒,到达的一定是1,所以走不到D,这时候就可以直接剪掉。起点是1,终点是0的情况也是一样的,所以只有当剩下的时间-最短路径是偶数时,才可能在剩下的时间刚好走到终点。

奇偶剪枝详见百度百科:点击打开链接

附上完整代码

#include<iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
using namespace std;
#define CRL(a,b) memset(a,b,sizeof(a))
typedef unsigned long long LL;
typedef  long long ll;

char map[10][10];
bool book[10][10];

int move_y[4]= {0,1,0,-1},
               move_x[4]= {1,0,-1,0},m,n,T,X,Y,Find=0,xd,yd;

void create(int n,int m) {
    for(int i=0; i<n; i++)
        scanf("%s",map[i]);

    for(int i=0; i<n; i++) {
        for(int j=0; j<m; j++) {
            if(map[i][j]=='S')  {
                X=i;
                Y=j;
            }
            if(map[i][j]=='D')  {
                xd=i;
                yd=j;
            }
        }
    }
}

void dfs(int x,int y,int time) {
    if(map[x][y]=='D'&&time==T) {
        cout<<"YES\n";
        Find=1;
        return;
    }

    int dis;                              //奇偶剪枝:判断在剩余时间里能否走到终点,不是充要条件
    dis=(T-time)-(fabs(x-xd)+fabs(y-yd));    // =剩下的时间-无障碍物下的最短路径
    if(dis<0||dis%2)  return;                //小于0或为奇数就剪掉

    for(int i=0; i<4; i++) {
        int next_x=x+move_x[i];
        int next_y=y+move_y[i];
        if(next_x<0||next_y<0||next_x>n-1||next_y>m-1||map[next_x][next_y]=='X'||book[next_x][next_y])
            continue;
        else {
            book[next_x][next_y]=1;
            dfs(next_x,next_y,time+1);
            if(Find)  return;
            book[next_x][next_y]=0;
        }
    }
    return;
}

int main() {
    while(~scanf("%d%d%d",&n,&m,&T)) {
        if(n==0&&m==0&&T==0)  break;
        Find=0;
        create(n,m);
        CRL(book,0);
        book[X][Y]=1;
        dfs(X,Y,0);
        if(!Find)
            cout<<"NO\n";
    }
    return 0;
}

还有一开始写错了的bfs,在t秒内能否到达door(未找题测试,仅供参考)

 

#include<iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
using namespace std;
#define CRL(a) memset(a,'X',sizeof(a))
typedef unsigned long long LL;
typedef  long long ll;

struct node {
    int x,y,pre;
} way[50];

int move_y[4]= {0,1,0,-1},
               move_x[4]= {1,0,-1,0},m,n,T;

char map[10][10];

void create(int n,int m) {
    getchar();
    CRL(map);
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=m; j++) {
            scanf("%c",&map[i][j]);
            if(map[i][j]=='S') {
                way[1].x=j;
                way[1].y=i;
                way[1].pre=0;
            }
        }
        getchar();//吸收回车
    }
}

void bfs() {
    int X,Y,front=1,rear=1,m=0,n=1,time=0;
    while(1) {
        for(int i=0; i<4; i++) {
            X=way[front].x+move_x[i];
            Y=way[front].y+move_y[i];
            if(map[X][Y]=='D') {
                cout<<"YES\n";
                return;
            }

            if(map[X][Y]=='.') {
                rear++;
                m++;
                way[rear].x=X;
                way[rear].y=Y;
                map[X][Y]='@';		//用'@'只是调试时看着方便
            }
        }
        front++;
        if(--n==0) {
            if(m==0) {              //找不到一条新的路了
                cout<<"NO\n";
                return;
            } else {
                time++;
                if(time>=T) {       //时间到
                    cout<<"NO\n";
                    return;
                }
                n=m;
                m=0;
            }
        }
    }

}

int main() {
    while(cin>>n>>m>>T&&(n||m||T)) {
        create(n,m);
        bfs();
    }
    return 0;
}