hdu Tempter of the Bone

很典型的dfs题,但是涉及到很多的剪枝 。

奇偶剪枝:
是数据结构的搜索中,剪枝的一种特殊小技巧。
现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点,
s        
|        
|        
|        
+ e
 
如图所示(“|”竖走,“—”横走,“+”转弯),易证abs(ex-sx)+abs(ey-sy)为此问题类中任意情况下,起点到终点的最短步数,记做step,此处step1=8;
  
s  
  +  
| +      
|        
+ e
 
如图,为一般情况下非最短路径的任意走法举例,step2=14;
step2-step1=6,偏移路径为6,偶数(易证);
故,若t-[abs(ex-sx)+abs(ey-sy)]结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。
奇偶路径的大概意思就是:从初始位置能到达目标位置的任一路径长度  -   初始位置到目标位置的最短长度=偶数
#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"queue"
#include"string.h"
#include"string"
#define mx 105
using namespace  std;
char maze[mx][mx];
int n,m,T,sx,sy,ex,ey;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
bool flag;
bool  judge(int x,int y)
{
    if(x>=0&&x<n&&y>=0&&y<m&&maze[x][y]=='.') return true;
    return false;
}
void dfs(int  x,int y,int t)
{
    if(t>T||flag) return;
    if(t==T&&x==ex&&y==ey) {flag=true;return;}
    int temp=abs(x-ex)+abs(y-ey);//当前位置到目标位置的最短路径
    temp=T-t-temp;
    if(temp%2) return;//奇偶剪枝,不加这个一直tle也是醉了 。
    for(int i=0;i<4;i++)
    {
        int dx=x+dir[i][0];
        int dy=y+dir[i][1];
        if(judge(dx,dy))
        {
            maze[dx][dy]='X';
            dfs(dx,dy,t+1);
            maze[dx][dy]='.';
        }
    }
}
int main()
{

    int i,j,blocks;
    while(cin>>n>>m>>T,n&&m&&T)
    {
        flag=false;blocks=0;
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                cin>>maze[i][j];
                if(maze[i][j]=='S')
                {
                    sx=i;sy=j;maze[i][j]='X';
                }
                else if(maze[i][j]=='D')
                {
                    ex=i;ey=j;maze[i][j]='.';
                }
                else if(maze[i][j]=='X') blocks++;
            }
        }
        if(n*m-blocks-1>=T)//如果给定的时间数比能走的格子数还要大的话,就肯定不满足条件了
        dfs(sx,sy,0);
        if(flag) cout<<"YES"<<endl;
        else  cout<<"NO"<<endl;
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/acm-jing/p/4435143.html