题意:从S走到D,D只有在t时会开,走过的点不能再访问,问是否能在t时走到D
挺BFS套路的题。。但是为了训练DFS的思想所以用DFS进行求解了~
首先记录S和D的位置(sx,sy)(ex,ey)
从(sx,sy)开始dfs,设初始时刻为0
将访问过的点设为’X’,D在非t时刻都为’O’
从每个点的上下左右方向中有’.’的位置分别dfs,并且在有’O’的位置判断下一时刻是否为t,是则说明能到达
每次访问完一种情况后将访问点再重置为’.’
然后是剪枝:
如果已经可以到达,则不再继续dfs;
然后用奇偶剪枝优化:
某位置(x,y)到(ex,ey)的最小路程长度是(abs(x-ex)+abs(y-ey)),并且如果中间有障碍物绕开时,一定是增加偶数个(可以是0个):
S
↓
↓
↓
↓ → → →DS
↓ →
X ↓
←↓
↓ → → →D
(2个)S
↓ →
X ↓
↓
→ → →D
(0个)
因此如果当前点能到达D,那么它们的距离(abs(x-ex)+abs(y-ey))+偶数步=剩下来的时间(t-time)
因此如果 (t-time)-(abs(x-ex)+abs(y-ey))为奇数,则一定不能到达,直接return
最后打印结果即可~
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int N=10;
int n,m,t,ans=0;
int sx,sy,ex,ey;
char maze[N][N];
int flag=0;
void dfs(int x,int y,int time){
if(flag) return;
int temp=(t-time)-(abs(x-ex)+abs(y-ey));//奇偶剪枝
if(temp<0||temp&1) return;
if(time==t){
maze[ex][ey]='D';
}
else{
maze[ex][ey]='O';
}
maze[x][y]='X';
for(int dy=-1;dy<=1;dy++){
int ny=y+dy;
if(ny>=0&&ny<m){
if(maze[x][ny]=='O'&&time+1==t){
flag=1;
return;
}
else if(maze[x][ny]=='.'){
dfs(x,ny,time+1);
maze[x][ny]='.';
}
}
}
for(int dx=-1;dx<=1;dx++){
int nx=x+dx;
if(nx>=0&&nx<n){
if(maze[nx][y]=='O'&&time+1==t){
flag=1;
return;
}
if(maze[nx][y]=='.'){
dfs(nx,y,time+1);
maze[nx][y]='.';
}
}
}
}
int main(){
while(~scanf("%d %d %d",&n,&m,&t)&&n&&m&&t){
flag=0;
getchar();
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%c",&maze[i][j]);
if(maze[i][j]=='S'){
sx=i;sy=j;
}
else if(maze[i][j]=='D'){
ex=i;ey=j;
}
}
getchar();
}
dfs(sx,sy,0);
flag?puts("YES"):puts("NO");
}
}
/*
2 3 3
S.X
..D
*/