hdu1010 Tempter of the Bone

题意:在一个n*m迷宫上,规定一个起点和终点,有墙‘X’ ,问起点到终点能不能恰好K步,走过的路不能再走。

思路:暴力深搜,直接TLE。

自己想了好几种剪枝,最重要的剪枝:map奇偶剪枝之前没有接触过...就一直TLE。

介绍一下奇偶剪枝,在对一个地图进行01编号

    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。
也就是说,如果当前的狗所在的坐标与D的坐标奇偶性不一样,那么狗需要走奇数步。
同理,如果狗所在坐标与D的坐标奇偶性一样,那么狗需要走偶数步数。
 
也就是说,狗的坐标x、y和对2取余是它的奇偶性,Dxy和对2取余是D的奇偶性。
两个奇偶性一加再对2取余,拿这个余数去与剩下时间对2取余的余数作比较即可。

很明显,如果起点在0 而终点在1 那显然 要经过奇数步才能从起点走到终点,依次类推,奇偶相同的偶数步,奇偶不同的奇数步在读入数据的时候就可以判断,并且做剪枝,当然做的时候并不要求把整个矩阵0,1刷一遍,读入的时候起点记为(Si,Sj) 终点记为(Di,Dj) 判断(Si+Sj) 和 (Di+Dj) 的奇偶性就可以了。

还有几个常见的剪枝

1.地图上能走的点数小于要求的步数,直接NO

2,最初出发点到目的点的最短路径小于要求步数,直接NO,还可以推出在搜索过程中当前点到目的点的最短路程小于还剩小路程.

3.在搜索过程步数已经大于等于要求步数,还没找到,或者是到了目的地,步数不对。

剪完后 78ms可以过

#include<bits/stdc++.h>
using namespace std;
char M[10][10];
int sx,sy,mx,my,n,m,w,flag,nxt[4][2]={0,1,1,0,0,-1,-1,0};
void dfs(int x,int y,int cur)
{
    if(x==mx&&y==my){
        if(cur==w) flag=1;
        return;
    }
    if(abs(x-mx)+abs(y-my)>w-cur) return;//可惜没神马卵用。
    if(cur>=w) return;
    for(int i=0;i<4;i++){
         int tx=x+nxt[i][0];
         int ty=y+nxt[i][1];
         if(tx<0||ty<0||tx>=n||ty>=m||M[tx][ty]=='X') continue;
         M[tx][ty]='X';
         dfs(tx,ty,cur+1);
         if(flag) return;
         M[tx][ty]='.';
    }
}

int main()
{
   while(scanf("%d %d %d",&n,&m,&w)){
       if((n+m+w)==0) return 0;
       int wall=0;flag=0;
       for(int i=0;i<n;i++){
           scanf("%s",M[i]);
           for(int j=0;j<m;j++){
            if(M[i][j]=='S') sx=i,sy=j;
            else if(M[i][j]=='D') mx=i,my=j;
            else if(M[i][j]=='X') wall++;
           }
       }
       if((mx+my+sy+sx+w)%2||n*m-wall<=w||abs(sx-mx)+abs(sy-my)>w){
          printf("NO\n");
          continue;
       }
       M[sx][sy]='X';
       dfs(sx,sy,0);
       if(flag) printf("YES\n");
       else printf("NO\n");
   }
}


你可能感兴趣的:(hdu1010 Tempter of the Bone)