hdu1010详解 TLE如何解决

题目链接:hdu1010


这一题是需要剪枝的,会用到一个小技巧:奇偶剪枝,否则就会TLE。

奇偶剪枝:
是数据结构的搜索中,剪枝的一种特殊小技巧。
如图所示(“|”竖走,“—”横走,“+”转弯),
现假设起点为(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步恰好到达。
(可以这样理解:上图s点到e点最近的路程是右移a=4步,下移b=4步,无论是先下移再右移,还是先右移再下移,还是下移的过程中同时右移,最后的结果都是最少需要右4步下4步才能到达e点。那么如果你从s点到e点,在左右方向共走了c步,在上下方向走了d步,可以肯定c>=a,d>=b(否则是到不了e点的),(c-a)一定是偶数,因为你右移a步后,每左移一步一定需要再右移一步回到e点,所以c-a是偶数。同理(d-b)也是偶数。即:如果t步从s点到了e点,那么t-[abs(ex-sx)+abs(ey-sy)]一定是个偶数)
#include<bits/stdc++.h>
int m,n,i,j,t;
char p[10][10];
int vis[10][10];//用来标记点是否已被走过.
int flag,dx,dy;
int v[4][2]={{0,-1},{-1,0},{1,0},{0,1}};
void dfs(int a, int b,int time)
{
    if(flag==1)
    return;
    if(p[a][b]=='D'&&time==t)
    {
        flag=1;
        return;
    }
    int temp=t-time-abs(a-dx)-abs(b-dy);
    if(temp%2)//奇偶剪枝,如果temp为奇数,可以肯定绝对无法在t时刻到达D点.
    return;
    for(int k=0;k<4;k++)//这个for循环是对点(a,b)上下左右四个方向的遍历.即点(a+0,b+(-1)),(a+(-1),b+0),(a+1,b+0),(a+0,b+1).
    {
        int va=a+v[k][0];
        int vb=b+v[k][1];
        if(va>=0&&vb>=0&&va<n&&vb<m&&p[va][vb]!='X'&&!vis[va][vb])
        {
            vis[va][vb]=true;
            dfs(va,vb,time+1);
            vis[va][vb]=false;
        }
    }
    
}
int main()
{
    while(scanf("%d%d%d",&n,&m,&t)!=EOF)
    {
        if(n==0&&m==0&&t==0)
        break;
        int sx,sy,x=0;
        memset(vis,false,sizeof(vis));
        getchar();
        flag=0;
        for(i=0;i<n;i++)
        for(j=0;j<m;j++)
        {
            scanf("%c",&p[i][j]);
            if(p[i][j]=='S')
            {
                sx=i;
                sy=j;
                vis[i][j]=true;
            }
            if(p[i][j]=='X')
            x++;
            if(p[i][j]=='D')
            {
                dx=i;
                dy=j;
            }
            if(j==m-1)
            getchar();
        }
        if(n*m-x-1-abs(sx-dx)>=abs(sy-dy))
        dfs(sx,sy,0);
        if(flag==1)
        {
            printf("YES\n");
        }
        else 
        printf("NO\n");
    }
    
}


 

参考博客:https://www.cnblogs.com/zhourongqing/archive/2012/04/28/2475684.html 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值