Robot Motion HDU - 1035(奇异DFS)

题目的大意就是给你一个地图,地图上不是传统的.和# 等等东西,而是方向N S W E ,你走到那个点,那个点是什么方向就是接下来你走的方向,一开始会给你入口(一开始的方向点),判断能不能走出迷宫(四个边界,走出任意一个都可以),如果走不出去(在地图里面循环的情况)。走出就求出步数,走不出去,就写出一开始走几步就开始了几个一周期的循环(步数表示)。

一个机器人已经被编程成按照其路径上的指令进行操作。机器人下一个移动方向的指令被放置在一个网格中。可能的指示是              N北(上一页)              

南部(下页)              

东面(页面右侧)              

W西(页面左侧)              

例如,假设机器人从网格1的北侧(顶部)开始,向南(向下)开始。机器人所遵循的路径如图所示。机器人在离开网格前要经过网格中的10个指令。              

比较网格2中发生的情况:机器人只执行一次3个指令,然后开始循环8个指令,并且永远不会退出。              

你要写一个程序来决定机器人离开网格需要多长时间,或者机器人是如何循环的。              

输入              

将有一个或多个网格供机器人导航。每个数据的格式如下。第一行是三个由空格分隔的整数:网格中的行数、网格中的列数以及机器人从北方进入的列数。可能的条目列从左边的一列开始编号。然后是方向指示的行。每个网格将至少有一行,最多有10行和10列指令。指令行只包含N、S、E或W字符,没有空格。输入的结尾由包含0 0 0的行指示。              

输出              

对于输入中的每个网格,都有一行输出。要么机器人遵循一定数量的指令,从任意一个四面的网格中退出,要么机器人遵循一定数量位置上的指令一次,然后重复某些位置上的指令。下面的示例输入对应于上面的两个网格,并说明了两种输出形式。无论数字是否在1之前,单词“step”总是紧跟“(s)”。 

Sample Input

3 6 5
NEESWE
WWWESS
SNWWWW
4 5 1
SESWE
EESNW
NWEEN
EWSEN
0 0 

Sample Output

10 step(s) to exit
3 step(s) before a loop of 8 step(s)

代码:

#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
const int maxn=1005;
typedef long long ll;

#include<bits/stdc++.h>
using namespace std;

char maap[maxn][maxn];
int vis[maxn][maxn];


int m,n;
int start;
bool flag=false;
int step;
int loop,beloop;

void dfs(int x,int y,int s)
{
	// 先判断越不越界  ,越界直接就可以走出      
	if(x<0||y<0||x>=m||y>=n)
	{
		flag=true;
		return ;
	}	
	
	
	step=s;	
	if(!flag)   					//判断是否找到  
	{
		if(!vis[x][y])				//判断是否循环回去了	
		{
			vis[x][y]=s;			//标记步数	
			if(maap[x][y]=='N')
				dfs(x-1,y,s+1);
			else if(maap[x][y]=='S')
				dfs(x+1,y,s+1);
			else if(maap[x][y]=='E')
				dfs(x,y+1,s+1);
			else if(maap[x][y]=='W')
				dfs(x,y-1,s+1);	
		}
		else
		{
			beloop=vis[x][y]-1;
			loop=s-vis[x][y];
		}
	}
	
}

int main()
{
	
	int i,j;
	while(cin>>m>>n>>start)
	{
		if(m==0&&n==0&&start==0)
			break;
		flag=false;
		memset(vis,0,sizeof(vis));	
		for(i=0;i<m;i++)
			for(j=0;j<n;j++)
				cin>>maap[i][j];	
		dfs(0,start-1,1);
	
		if(flag)
			 printf("%d step(s) to exit\n",step);
		else
			printf("%d step(s) before a loop of %d step(s)\n",beloop,loop);


	}
	
	
	return 0;
}

题目要求 如果能走出去,输出步数,如果走不出去,输出2个数据,循环之前走了几步,循环周期是多少。首先看看怎么判断出现循环的情况,拿一个标记数组,走过的点都标记上(就用来装步数的就可以),如果出现循环,就可以判断vis标记数组有没有数据。如果能走出去,就看是否越界出了地图。在DFS函数的开头,就判断是否越界。一越界就直接 一路 return(这个bool 类型的变量用的很好,在往下递归途中 可以判断一下,在输出结果时也可以判断)。接下来就是步数的问题, 递归函数有三个参数,前两个都是坐标,后一个是当前步数,在可以出去的情况下,直接输出这个步数就可以。在不可以出去的情况下,我们需要另外引进两个变量,刚刚进入循环时的 那个步数,这个就是代码放的位置了, 如果已经找到循环的情况,但我们已经把步数给他更新了(一开始已经来过的位置有步数),我们就不能得到那个进来前的步数,怎么办呢,那我们就不更新,在更新之前就判断是不是标记过了。

if(!vis[x][y])				//判断是否循环回去了	
		{
			vis[x][y]=s;			//标记步数	
			if(maap[x][y]=='N')
				dfs(x-1,y,s+1);
			else if(maap[x][y]=='S')
				dfs(x+1,y,s+1);
			else if(maap[x][y]=='E')
				dfs(x,y+1,s+1);
			else if(maap[x][y]=='W')
				dfs(x,y-1,s+1);	
		}

如果标记了,直接这个进来点步数 -1(就是进循环之前步数),总的步数减去已经标记时的步数(到这里时,这个点已经包括到总步数了,减去他就是循环周期了)

else
		{
			beloop=vis[x][y]-1;
			loop=s-vis[x][y];
		}

新的写法吧;

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值