4 4 5 S.X. ..X. ..XD .... 3 4 5 S.X. ..X. ...D 0 0 0
NO YES
要点:
1、每个block只能走一次
2、要求恰好某个给定的时间到达出口
算法分析:
迷宫==搜索无疑,关键在于剪枝。
1、若时间大于剩余可行走block,则必定失败。
2、
可以把map看成这样:
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
从为 0 的格子走一步,必然走向为 1 的格子
从为 1 的格子走一步,必然走向为 0 的格子
即:
0 ->1或1->0 必然是奇数步
0->0 走1->1 必然是偶数步
结论:
所以当遇到从 0 走向 0 但是要求时间是奇数的,或者, 从 1 走向 0 但是要求时间是偶数的 都可以直接判断不可达!关于这句话在本题中的使用,我是这样理解的,假设有一条最短路径p,我们若每偏离p路径一次,就需要增加2或者0才能达到目的地,因此该路径的奇偶性与时间必定等同。
深搜代码如下:
# include <iostream>
char map[9][9];
int n,m,t,di,dj;
bool escape;
int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
void dfs(int si,int sj,int cnt)
{ int i,temp;
if(si>n||sj>m||si<=0||sj<=0) return;
if(cnt==t&&si==di&&sj==dj) escape=1;
if(escape) return;
temp=(t-cnt)-abs(si-di)-abs(sj-dj); //(t-cnt)为剩余分钟,abs(si-di)+abs(sj-dj)为最少需要步数,
//若前者小于后者则一定失败,若二者的奇偶性不同也一定失败
if(temp<0||temp&1) return;
for(i=0;i<4;i++){ //尝试相邻四个可能位置
if(map[si+dir[i][0]][sj+dir[i][1]]!='X')
{
map[si+dir[i][0]][sj+dir[i][1]]='X'; //已走过,置为x
dfs(si+dir[i][0],sj+dir[i][1],cnt+1);
map[si+dir[i][0]][sj+dir[i][1]]='.'; //向上一步回溯时把该方格仍置为空
}
}
return;
}
int main()
{
int i,j,si,sj;
while(std::cin>>n>>m>>t)
{
if(n==0&&m==0&&t==0) break;
int wall=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
std::cin>>map[i][j];
if(map[i][j]=='S') { si=i; sj=j; } //si,sj 记下入口位置
else if(map[i][j]=='D') { di=i; dj=j; } //di,dj记下出口位置
else if(map[i][j]=='X') wall++; //统计墙的总数
}
if(n*m-wall<=t) //可走的block的总数小于时间
{
std::cout<<"NO"<<"\n";
continue;
}
escape=0;
map[si][sj]='X';
dfs(si,sj,0);
if(escape) std::cout<<"YES"<<"\n";
else std::cout<<"NO"<<"\n";
}
return 0;
}HDU 1010 Tempter of the Bone(DFS+奇偶性剪枝),布布扣,bubuko.com
HDU 1010 Tempter of the Bone(DFS+奇偶性剪枝)
原文:http://blog.csdn.net/u014492609/article/details/38510057