题目:传送门
分析:模拟题,小狗每个位置只能走一次并且不能回头走走过的位置,因为门会在第T秒开,所以要找到一条路劲使得小狗到第T秒时到达门口,属于DFS入门,但是涉及到剪枝,否则会超时,要注意细节,本人超时了十多次。
解题:四个剪枝
(1)当tt>t时剪枝;
(2)搜寻到最后一个解时剪枝;
(3)奇偶剪枝(关键):当前走到终点步数的奇偶性应该与满足条件还需要走的步数奇偶性一致,所以到终点步数与还需走的步数相减的和应该为偶数。
(4)当前走到终点最少步数>满足条件还需要走的步数剪枝(关键)
将(3)(4)合并写为remain=abs(ex-x)+abs(ey-y)-(t-tt)
所以判断条件为if(remain>0||remain%2) return;
AC代码:
#include<iostream>
#include<cstring>
using namespace std;
int n,m,t;
int dir[4][2]= {-1,0,1,0,0,-1,0,1}; //四个方向遍历
char maze[10][10];
int sx,sy,ex,ey;
bool vis[15][15];
bool flag;
int abs(int a) {
return a<0?-a:a;
}
void dfs(int x,int y,int tt) {
vis[x][y]=true; //标记已走
if(tt>t) return; //第一个剪枝
if(flag) return; //已达到最后一个解剪枝
if(tt==t&&maze[x][y]=='D') {
flag=true;
return;
}
int remain=abs(ex-x)+abs(ey-y)-(t-tt); //第三四个剪枝
if(remain>0||remain%2) return;
for(int i=0; i<4; i++) { //往四个方向遍历
int X=x+dir[i][0],Y=y+dir[i][1];
if(vis[X][Y]||X<0||X>=n||Y>=m||Y<0||maze[X][Y]=='X') continue;
dfs(X,Y,tt+1);
vis[X][Y]=false;
}
}
int main() {
while(cin>>n>>m>>t) {
if(n==0&&m==0&&t==0) break;
flag=false;
memset(vis,false,sizeof(vis)); //全部标记为未走
for(int i=0; i<n; i++) {
scanf("%s",maze[i]);
for(int j=0; j<m; j++) {
if(maze[i][j]=='S') {
sx=i;
sy=j;
}
if(maze[i][j]=='D') {
ex=i;
ey=j;
}
}
}
dfs(sx,sy,0);
if(flag) printf("YES\n");
else printf("NO\n");
}
}