HDU 1010

来源:互联网 发布:windows phone 10小米 编辑:程序博客网 时间:2024/05/24 11:14

题目链接:点击打开链接

题意:根据地图,'S'为开始位置,'D'为门的位置,' . '为空地,'X'为墙,不能经过,问:在指定的时间,是否能到达'门'的位置.

注意:路不可以重复经过,时间也要刚好是 t ,不能少.

思路:还是DFS,不能用BFS,因为BFS求的是最短路径,而此题的路径不一定最短.剪枝是关键,奇偶剪枝.

奇偶剪枝原理:

要理解奇偶剪枝,先了解一下曼哈顿距离,从一个点到达另外一个点的最短路径长度(时间)可以根据两点坐标求出。

路径长度(非最短)与最短路径的长度同奇偶,它们的差一定是偶数!举个例子,就像两个偶数的差差是偶数,两个个数

的差也是偶数.

本题还有一个剪枝:n*m-wall与t的关系,wall为'X'的数量,解释一下,n*m为区域总数,
所以m*n-wall<=t 一定不到到达终点,注意,少时等号在杭电上运行时间为546MS,而加上等号运行时间才为78MS!


eg: 

3 3 4
SXX
.XX
X.D

#include<iostream>#include<cstdio>#include<cmath>using namespace std;int d[4][2]={0,1,1,0,0,-1,-1,0};//表示方向char map[10][10];int sx,sy,ex,ey;//四个坐标int flag,step;int n,m,t;void dfs(int x,int y,int t){if(flag==1)return;// //若找到所需解,则不用再找其余路径 if(t<abs(ex-x)+abs(ey-y)||(t-abs(ex-x)+abs(ey-y))%2)return;/*  剪枝。若剩余时间-当前点到终点的横纵坐标之和,为偶数        则,该路,可走。(若无障碍,差值为0,若有障碍则绕道        即差值-1+(n*2+3)为偶数)*/else if(t==0){if(x==ex&&y==ey)//若此时,t=0且刚好到达终点,则标记找到所需解。  {flag=1;return;}else{return;}}elsefor(int i=0;i<4;i++)//每次向4个方向探。{int nx=x+d[i][0];int ny=y+d[i][1];if(nx>0&&nx<=n&&ny>0&&ny<=m&&(map[nx][ny]=='.'||map[nx][ny]=='D'))//若该点不为墙,则为可走  {map[nx][ny]='X'; //标记走过dfs(nx,ny,t-1);  // 时间-1,递归下一点  map[nx][ny]='.'; //回溯,还原状态  }}return;}int main(){char str[10];while(scanf("%d%d%d",&n,&m,&t)){if(m==0&&n==0&&t==0)return 0;for(int i=1;i<=n;i++){scanf("%s",str);for(int j=1;j<=m;j++){ map[i][j]=str[j-1];    if(map[i][j]=='S')sx=i,sy=j;     else if(map[i][j]=='D')ex=i,ey=j;}}flag=0;dfs(sx,sy,t);if(flag==0)printf("NO\n");elseprintf("YES\n");}}


0 0
原创粉丝点击