傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=1010
先枚舉總步數,即開門週期的倍數,T,2*T,3*T,....iT<=總的可走方塊數
如下代碼:
for(int i = T;i<=block;i+=T){if(ok){break;}else dfs(st,0,i);}
然後進入dfs後各種剪枝:
if(ok)return;
if(u == en && num == iT){ok = 1;return;}///到達
if(num > iT)return;
int x = u/Nc,y = u%Nc;
if(abs(x-ex) + abs(y-ey)>iT-num)return;
if((iT - num - abs(x-ex) - abs(y-ey))%2)return;
各種剪枝:
已找到了一條路剪枝,當前步數超過總步數,剪枝
奇偶剪枝
已走步數+剩餘最短路步數>iT剪枝
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int N = 30;
int Nr,Nc,T,block;
int st,en;
int ex,ey;
int ok;
int maps[N][N];
int vis[N][N];
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
void dfs(int u,int num,int iT)
{
if(ok)return;
if(u == en && num == iT){ok = 1;return;}///到達
if(num > iT)return;
int x = u/Nc,y = u%Nc;
if(abs(x-ex) + abs(y-ey)>iT-num)return;
if((iT - num - abs(x-ex) - abs(y-ey))%2)return;
for(int i = 0;i<4;i++){
int newx = x + dir[i][0];
int newy = y + dir[i][1];
if(newx>=0 && newx<Nr && newy>=0 && newy <Nc && !maps[newx][newy] && !vis[newx][newy]){
int newu = newx*Nc + newy;
vis[newx][newy] = 1;
dfs(newu,num+1,iT);
vis[newx][newy] = 0;
}
}
}
int main()
{
char s[N];
char a;
//freopen("in.txt","r",stdin);
while(scanf("%d%d%d",&Nr,&Nc,&T) == 3){
a = getchar();
if(Nc == 0 && Nr == 0 && T == 0)break;
memset(vis,0,sizeof(vis));
ok = 0,block = 2;
for(int i = 0;i<Nr;i++){
scanf("%s",s);
for(int j = 0;j<Nc;j++){
if(s[j] == 'S'){vis[i][j] = 1;maps[i][j] = 0;st = i*Nc + j;}
else if(s[j] == '.'){maps[i][j] = 0;block++;}
else if(s[j] == 'X'){maps[i][j] = 1;}
else if(s[j] == 'D'){maps[i][j] = 0;ex = i,ey = j;en = i*Nc + j;}
}
}
for(int i = T;i<=block;i+=T){if(ok){break;}else dfs(st,0,i);}
if(ok)printf("YES\n");
else printf("NO\n");
}
return 0;
}