HDU1010(Tempter of the Bone)深搜

HDU1010 Tempter of the Bone
广搜每走
思路:简单的深搜,如果map[nextx][nexty]!='X',则以该最后点为当前节点继续搜,若继续搜没有路可走,则释放当前节点(即原来标记过,恢复为未标记,以便再以其他节点搜索时经过该点),回到上一节点,return.由于step是局部变量,其生命周期随着当前层的DFS()函数结束而结束,所以返回上一层时,step的值就是上一层的值,而不是下一层改变后的值,而visit数组因为是全局变量,因此其生命周期只有main函数结束后才结束,因此下一层对visit数组值的改变,在DFS()返回上一层时有影响,值不在是上一层的了,而是改变后的值。
刚开时不明白,逐句调试后才对深搜有了新的认识。
下面的代码,WA了好几次,就是因为把
visit[sx][sy]=1;
if(N*M-wall<=T) {printf("NO\n");continue;}
DFS(sx,sy,0);
写成
if(N*M-wall<=T) {flag=0;}
else{
DFS(sx,sy,0);visit[sx][sy]=1;}
会超时,现在也不知到为什么,可能是杭电OJ有问题吧;
#include<stdio.h>
#include<string.h>
#include<math.h>
int visit[10][10];
int dir[4][2]={-1,0,1,0,0,1,0,-1};
char map[10][10];
int T,N,M;
int flag;
int dx,dy;
void DFS(int sx,int sy,int step)
{
int i,nextx,nexty;
        //下面两行是每次调用DFS(),进入下一层节点时,对其进行检查;
if(map[sx][sy]=='D'&&step==T) {flag=1;return;}   //如果已经搜到‘D',并满足条件就返回上一层节点
if((map[sx][sy]=='D'&&step<T)||step>T)return;    //如果。。。。。。,但是不满足条件则也返回上一层(由上一层的位置搜索其他路径);
for(i=0;i<4;i++)
{

nextx=sx+dir[i][0];
nexty=sy+dir[i][1];
//如果当前节点,某个方向上的下一个节点不越界,并且没有走过
if(nextx<=M&&nextx>=1&&nexty<=N&&nexty>=1&&visit[nextx][nexty]==0)
{    
//如果该方向上的节点可以走,标记该节点,并搜索该节点的下一个方向上的节点;
if(map[nextx][nexty]!='X')        
{visit[nextx][nexty]=1;
DFS(nextx,nexty,step+1);
if(flag) return;     //下一层返回该层时,如果已找到满足条件的路径,则不用再搜该节点其他方向上的节点路径,直接返回该节点的上一层(优化时间);
visit[nextx][nexty]=0;//释放已搜索过当前节点的下一层节点;
}
}
}
}
   
int main()
{
int i,j,wall,sx,sy;
while(scanf("%d%d%d",&M,&N,&T),(N+M+T)!=0)
{
memset(visit,0,sizeof(visit));
flag=0;wall=0;
   getchar();
for(i=1;i<=M;i++)
{ 


for(j=1;j<=N;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]=='S')
{
sx=i;sy=j;
}

if(map[i][j]=='X')
wall++;
}
          getchar();
} 
    visit[sx][sy]=1;
if(N*M-wall<=T) {printf("NO\n");continue;}//如果能走的点小于T步,则直接输出(优化时间效率);取等号的原因:如果T=6,最多能走的有6个点,其最多能走5步;
      DFS(sx,sy,0);


if(flag)printf("YES\n");
else printf("NO\n");
}
return 0;
}


刚开始使用的广搜,最后别人说不能用广搜,最后才知道原因:
下面是广搜代码:
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
char map[10][10];
int dir[4][2]={0,1,0,-1,1,0,-1,0};
int visit[10][10];
int n;
int m;
int T;
struct node
{
    int x;
    int y;
    int step;
};
int BFS(int sx,int sy)
{
    queue<node>Q;
    node cur,next;
    int i,flag=0,sum;
    cur.x=sx;cur.y=sy;
    visit[cur.x][cur.y]=1;
    cur.step =0;
    Q.push(cur);
    while(!Q.empty ())
    {
        cur=Q.front();
            Q.pop ();
        for(i=0;i<4;i++)
        {
            next.x=cur.x+dir[i][0];
            next.y=cur.y+dir[i][1];
            next.step=cur.step+1;
            sum=next.step;
            if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m&&visit[next.x][next.y]==0)
            {
                if(map[next.x][next.y]=='.')
                {
                    Q.push(next);
                    visit[next.x][next.y]=1;
                }
                if(sum>T)return 0;
                else if(map[next.x][next.y]=='D'&&sum==T)
                    {
                        flag=1;return 1;
                    }
                else if(map[next.x][next.y]=='D'&&sum<T)
                    return 0;      
            }
            
        }
    }
    if(flag==0) return 0;
}
int main()
{
    int i,j,sx,sy,sun;
    while(scanf("%d%d%d",&n,&m,&T)!=EOF)
    {   
        if(n+m+T==0)break;
        memset(visit,0,sizeof(visit));
        memset(map,0,sizeof(map));  
        for(i=1;i<=n;i++)
        {
            getchar();
            for(j=1;j<=m;j++)
            {
              scanf("%c",&map[i][j]);
              if(map[i][j]=='S')
              {sx=i;sy=j;}
            }
        }
        sun=BFS(sx,sy);
        if(sun==0)printf("No\n");
        else printf("YES\n");
    }
    return 0;
}


如测试实例:
S.X.
.XD.
...X
...X
T=4;
可能路径是:'S'->(2,1)->(3,1)->(4,1)->(4,2)->(4,3)->(3,3)->'D'一共7七步,
还可能的路径是'S'->(2,1)->(3,1)->(3,2)->(3,3)->'D' 共4步;
如果先通过第一种到达了'D',由于(3,3)已被标记走过,所以会找不到符合条件的路径,不像深搜那样找不到,释放路径,可以返回去重找。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值