ACM 广搜 Hero In Maze

这是Hero In Maze三道题,分别是TOJ中Hero In Maze简单版,普通版,提高版。

以下我将一一阐述。

 

TOJ 2777 Hero In Maze简单版

描述

 

500年前,Jesse是我国最卓越的剑客。他英俊潇洒,而且机智过人^_^。

突然有一天,Jesse心爱的公主被魔王困在了一个巨大的迷宫中。Jesse听说这个消息已经是两天以后了,他急忙赶到迷宫,开始到处寻找公主的下落。

请你判断他是否能救出心爱的公主。(假设有路可以通到公主那就可以找到公主)。

 

输入

 

题目包括多组测试数据。
每组测试数据以两个整数n,m(0<n, m≤20)开头,分别代表迷宫的长和高。紧接着有m行,n列字符,由".","*","P","S"组成。其中
"." 代表能够行走的空地。
"*" 代表墙壁,Jesse不能从此通过。
"P" 是公主所在的位置。
"S" 是Jesse的起始位置。
Jesse只能选择上、下、左、右任意一方向走一步。
输入以0 0结束。

 

输出

如果能救出公主输出YES,否则输出NO。

样例输入

4 4 .... .... .... S**P 4 4 .... .... **** S**P 0 0

样例输出

YES NO

这个用深搜就可以,直接判断能不能从S走到P即可。

 

#include <stdio.h>
int a,b,s,k=0;
char m[21][21];	
int dir[4][2]={1,0,0,1,-1,0,0,-1};
void dfs(int x,int y)
{  
   if(m[x][y]=='P')
   k=1;
	m[x][y]='*';
	int i,xx,yy;
   for(i=0;i<4;i++)
   {
   	xx=x+dir[i][0];
   	yy=y+dir[i][1];
   	if(xx>=0&&xx<a&&yy>=0&&yy<b&&m[xx][yy]!='*')
    dfs(xx,yy);
   }	
}
int main()//2777
{
	int i,j,u,w;
	while(scanf("%d%d",&a,&b))
	{   
	    s=0;k=0;
		if(a==0&&b==0)break;			
		for(i=0;i<a;i++)
		{getchar();
			for(j=0;j<b;j++)
			{
				scanf("%c",&m[i][j]);
			   if(m[i][j]=='S')
			    u=i,w=j;
			}
		} 
		dfs(u,w);
		if(k==0)
		printf("NO\n");
		else
		printf("YES\n");
	}
}

 

TOJ 1005 Hero In Maze

 

描述

 

500年前,Jesse是我国最卓越的剑客。他英俊潇洒,而且机智过人^_^。

突然有一天,Jesse心爱的公主被魔王困在了一个巨大的迷宫中。Jesse听说这个消息已经是两天以后了,他知道公主在迷宫中还能坚持T天,他急忙赶到迷宫,开始到处寻找公主的下落。
时间一点一点的过去,Jesse还是无法找到公主。最后当他找到公主的时候,美丽的公主已经死了。从此Jesse郁郁寡欢,茶饭不思,一年后追随公主而去了。T_T
500年后的今天,Jesse托梦给你,希望你帮他判断一下当年他是否有机会在给定的时间内找到公主。

他会为你提供迷宫的地图以及所剩的时间T。请你判断他是否能救出心爱的公主。

 

输入

 

题目包括多组测试数据。
每组测试数据以三个整数N,M,T(0<n, m≤20, t>0)开头,分别代表迷宫的长和高,以及公主能坚持的天数。
紧接着有M行,N列字符,由".","*","P","S"组成。其中
"." 代表能够行走的空地。
"*" 代表墙壁,Jesse不能从此通过。
"P" 是公主所在的位置。
"S" 是Jesse的起始位置。
每个时间段里Jesse只能选择“上、下、左、右”任意一方向走一步。
输入以0 0 0结束。

 

输出

 

如果能在规定时间内救出公主输出“YES”,否则输出“NO”。

 

样例输入

4 4 10 .... .... .... S**P 0 0 0

样例输出

YES

题目意思与上面一致,但是这题要判断时间,所以不能用深搜了,需要用广搜来计算最短时间。

这是一个大佬写的,我没看懂...

http://blog.csdn.net/j_sure/article/details/19997869

 

#include <cstdio>  
#include <iostream>  
#include <algorithm>  
#include <cstring>   
#include <queue>  

using namespace std;   
int DTx[4]={-1,0,1,0};  
int DTy[4]={0,1,0,-1};  
char map[25][25];  
int dp[25][25];  
int x,y,X,Y;  
int minn;  
int n,m,t;  
struct H{  
    int x,y;  
    int time;  
};  
int bfs(int h,int z)  
{  
    int i,j;  
    queue <H> q;  
    H a,b,c;  
    a.x=h;  
    a.y=z;  
    a.time=0;  
    q.push(a);  
    while(!q.empty())  
    {  
        b=q.front();  
        q.pop();  
        if(b.x==X&&b.y==Y)  
            return b.time;  
        for(i=0;i<4;i++)  
        {  
            c.x=b.x+DTx[i];  
            c.y=b.y+DTy[i];  
            if(c.x>=0&&c.x<m&&c.y>=0&&c.y<n&&!dp[c.x][c.y])  
                {  
                    dp[c.x][c.y]=1;  
                    c.time=b.time+1;  
                    q.push(c);  
                }  
        }  
    }  
    return -1;  
}  
int main()  
{  
    int i,j;  
    while(~scanf("%d%d%d",&n,&m,&t)&&(n||m||t))  
    {  
        memset(dp,0,sizeof dp);  
        for(i=0;i<m;i++)  
            cin>>map[i];  
        for(i=0;i<m;i++)  
            for(j=0;j<n;j++)  
            if(map[i][j]=='S')  
            {x=i;y=j;dp[i][j]=1;}  
            else if(map[i][j]=='P')  
            {X=i;Y=j;}  
            else if(map[i][j]=='*')  
                dp[i][j]=1;  
        minn=bfs(x,y);   
        //printf("%d\n",minn);   
        if(minn<=t&&minn!=-1)  
        printf("YES\n");  
        else 
	printf("NO\n");  
    }  
    return 0;  
}  

 

TOJ 3305 Hero In Maze ||

 

描述

 

500年前,Jesse是我国最卓越的剑客。他英俊潇洒,而且机智过人^_^。
突然有一天,Jesse心爱的公主被魔王困在了一个巨大的迷宫中。Jesse听说这个消息已经是两天以后了,他急忙赶到迷宫,开始到处寻找公主的下落。令人头痛的是,Jesse是个没什么方向感的人,因此,他在行走过程中,不能转太多弯了,否则他会晕倒的。 我们假定Jesse和公主所在的位置都是空地,初始时,Jesse所面向的方向未定,他可以选择4个方向的任何一个出发,而不算成一次转弯。希望你帮他判断一下他是否有机会找到心爱的公主。 

 

输入

 

题目包括多组测试数据.

第1行为一个整数T(1 ≤ T≤ 100),表示测试数据的个数,接下来为T组测试数据.

每组测试数据以两个整数N,M,K(1<=N, M≤100, 0<K<=10)开头,分别代表迷宫的高,长和Jesse最多能转的弯数,(紧接着有N行,M列字符,由".","*","P","S"组成。其中
"." 代表能够行走的空地。
"*" 代表墙壁,Jesse不能从此通过。
"P" 是公主所在的位置。
"S" 是Jesse的起始位置。
每个时间段里Jesse只能选择“上、下、左、右”任意一方向走一步。

 

输出

 

如果Jesse能在晕之前找到公主,输出“YES”,否则输出“NO”。

 

样例输入

2 5 5 1 P..** *.**. S.... ..... *.... 5 5 2 P..** *.**. S.... ..... *....

样例输出

NO YES

题目意思与上一致,就是判断条件从时间变成了转弯次数。注意初始的一次不算转弯。

判断转弯次数的话我设置了一个wan,即第一次转的方向(i)和第二次的不一样时,就是转弯了。

然后我写的广搜TOJ没AC,但是我感觉完美了...先放上来吧~

 

#include <cstdio>  
#include <iostream>  
#include <algorithm>  
#include <cstring>  
#include <cmath>  
#include <queue>
using namespace std;   
int DTx[4]={-1,0,1,0};  
int DTy[4]={0,1,0,-1};  
char map[101][101];  
int dp[101][101];  
int x,y,X,Y;  
int minn;  
int n,m,t;  
struct H{  
    int x,y;  
    int time,wan;  
};  
int bfs(int h,int z)  
{  
    int i,j;  
    queue <H> q;  
    H a,b,c;  
    a.x=h;  
    a.y=z;  
    a.time=-1; 
	a.wan=-1; 
    q.push(a);  
    while(!q.empty())  
    {  
        b=q.front();  
        q.pop();  
        if(b.x==X&&b.y==Y)  
            return b.time;  
        for(i=0;i<4;i++)  
        {  
            c.x=b.x+DTx[i];  
            c.y=b.y+DTy[i];  
            c.wan=i;
            if(c.x>=0&&c.x<m&&c.y>=0&&c.y<n&&!dp[c.x][c.y])  
                {  
                    dp[c.x][c.y]=1;  
                    if(c.wan!=b.wan)//若两次方向一样,则没有转弯。 
                    c.time=b.time+1; 
					q.push(c); 
                }  
        }  
    }  
    return -1;  
}  
int main()  
{  
    int i,j,o;  
    scanf("%d",&o);
    while(o--)  
    {  
		scanf("%d%d%d",&m,&n,&t); 
        memset(dp,0,sizeof dp);  
        for(i=0;i<m;i++)  
            cin>>map[i];  
        for(i=0;i<m;i++)  
            for(j=0;j<n;j++)  
            if(map[i][j]=='S')  
            {x=i;y=j;dp[i][j]=1;}  
            else if(map[i][j]=='P')  
            {X=i;Y=j;}  
            else if(map[i][j]=='*')  
                dp[i][j]=1;  
        minn=bfs(x,y);   
        //printf("%d\n",minn);   
        if(minn<=t&&minn!=-1)  
        printf("YES\n");  
        else 
		printf("NO\n");  
    }  
    return 0;  
}  

 

然后下面的是童冰学姐写的深搜,简单很多。

 

#include<stdio.h>
int n,m,b[4][2]={{0,1},{0,-1},{1,0},{-1,0}},s,k;
char a[101][101];
void dfs(int x,int y,int r,int w)
{
    if(k==1)return;
    int i,x0,y0,r0;
    if(x<0||y<0||x>=n||y>=m||r>s+1||a[x][y]=='*')return;
    if(a[x][y]=='P')
	{k=1;return;}
    a[x][y]='*';
    for(i=0;i<4;i++)
    {
        x0=x+b[i][0];
        y0=y+b[i][1];
        if(w!=i)
        r0=r+1;
        else r0=r;
        dfs(x0,y0,r0,i);
    }
    a[x][y]='.';
}
int main()
{
    int i,j,x0,y0,t;
    scanf("%d",&t);
    while(t--)
    {
        k=0;
        scanf("%d%d%d",&n,&m,&s);
        for(i=0;i<n;i++)
        {
        	scanf("%s",a[i]);
        	for(j=0;j<m;j++)
        	{
            	if(a[i][j]=='S')
            	x0=i,y0=j;
        	}
		}
        dfs(x0,y0,0,-1);
        if(k)printf("YES\n");
        else printf("NO\n");
    }
}   

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值