HDU-1010 Tempter of the Bone (dfs+剪枝)

       题目:HDU-1010   Tempter of the Bone 

      题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010

Tempter of the Bone

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 97086    Accepted Submission(s): 26346



Problem Description
The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.

The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.
 

Input
The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:

'X': a block of wall, which the doggie cannot enter; 
'S': the start point of the doggie; 
'D': the Door; or
'.': an empty block.

The input is terminated with three 0's. This test case is not to be processed.
 

Output
For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise.
 

Sample Input
  
  
4 4 5 S.X. ..X. ..XD .... 3 4 5 S.X. ..X. ...D 0 0 0
 

Sample Output
  
  
NO YES
 

      这道题目说实话刚开始看我是不会的,写完dfs就傻了,实在不知道怎么把“时间”(也就是步数)的计算加进去,而且这道题目本身问的是能否在指定时间点逃生,也就是说不一定是最短路可能还是最长路也可能是中间徘徊之后才满足逃出条件,而且就算少于最长时间,多于最短时间也不一定能够恰好在指定时间到终点,但是稍微手动跑两次就发现是隔一个可以跑,不过就算发现了这些,还是没什么卵用,依然是束手无策。
      废话就不再说了,因为是第一道dfs的题目,所以会从无到有说一下dfs,之后遇到的dfs题目就不细讲了,首先说一下dfs(深度优先搜索)是一种搜索的算法,在ACM算法里面也是赫赫有名的一种,当然也是基础必须掌握的一种算法。它其实是一种基于树结构来进行搜索的,例如二叉树,dfs就是先搜索最底层的,然后依次向上搜索,而这种搜索大多数是基于递归来实现分支搜索的。而我们使用dfs解题也正是将题目转化为树形结构(仅仅是思想上,形式上还是原来的结构),其中最常见的就是迷宫搜索,给定起点,给定终点,给定障碍,我们就可以以从起点出发,利用递归,依次向上下左右搜索出口,然后再把上下左右每一个点当成初始点在进行搜索,这就类似于一种“树形结构”了,直到遇到障碍、遇到边界,那么搜索就停止了,遍历整张图以后就完成了搜索,搜索其实是一种思想,由此展开可以产生很多方面的问题,比如这一道题,所以需要具体问题具体对待,OK,来看这一道题。
      这个题目要求上面已经说过了,它的特别要求是:遇到墙走不通,走过的路不能再走,需要恰好在指定的时间走到终点。
      那么首先我们在输入图之后就要找到起点,从起点出发开始dfs,注意这里还有一个时间,所以我们搜索的变量传递一栏里面还需要加上一个时间,然后开始dfs,这中间当然会出现很多问题,比如,我刚开始写的时候没有在每个dfs之后把它的状态重新变为没有走过的,那么这个时候问题就产生了:我这样搜索的结果只相当于一种路径,只有伪最短路的搜索结果(也不一定就是最短路),一旦我第一步向右走成功了,那么第一步就被标记为“走过”了,那么之后的方法就不能再走了,也就是说一种走法对整张图造成了影响,这样明显是不正确的,所以在dfs的过程中一定要注意单次路径是否对其它路径产生了影响,如果不注意这点最后很可能产生似是而非的结果,错都不知道哪里错了。在解决完这个,将所有的路径都遍历之后,我们只需要在每次递归的时候都把附带的time++,那么time的值就是这个路径所花费的时间,我们只需要另外加一个全局变量bool来表示最终是否能逃脱的状态,每一次都判断是否到了终点而且时间是否是要求的结果(因为我们已经把所有的路径都搜索了一遍,所以如果有可以逃生的路径一定会满足条件的,不清楚的话可以跟着dfs模拟两次),如果是就把bool赋为true,最后加一个判断就行了。
      这个弄好之后貌似可以了,样例是可以过了,但是这道题却没有结束,这样的代码交上去是绝对超时的,因为递归的路径太多了所以本来就很容易超时。所以我们就需要进行剪枝,剪枝就是“剪去”不必要的搜索路径以避免不必要的时间浪费。当然以我的智商是无论如何也想不出来奇偶剪枝这种东西的,也是看了大神的博客才知道,但是我们自己可以想到的还有一些小地方是可以剪的:
            1.如果起点到终点的绝对最短路径(无视障碍)步数(也就是时间)都大于要求时间t的话,那也没必要走了,直接NO就行。
            2.如果所剩下的所有可以走的步数(除了墙以外)都小于要求时间t的话,那也没必要走了,NO。
            3.如果我们已经找到可以逃出的路径的话,那也没必要再dfs了,所以我们在dfs最开始加一个判断如果满足可以逃出ans=1;直接return减少不必要的寻找。
      之后就是神奇的奇偶剪枝了: 如果我们把一张图看成这个样子的话,我们很容易发现一个规律,从0走到0的时候用的步数是偶数步,0走到1时用的步数是奇数步,而这道题目要求的是恰好在一个时间点到达终点,也就是说知道起点坐标、终点坐标,我们就可以判断出最终的答案是奇数还是偶数,如果t不是我们计算出来的偶数或者奇数,那就可以直接NO掉,不用dfs,这个优化对于随机产生的测试数据来讲作用是显而易见的(当然对于特殊设计的数据来讲意义可能不是很明显),而加上这个判断只需要在输入时稍加判断就行,何乐而不为。
      由此可见,搜索题目考验的绝对不仅仅是搜索,更重要的是剪枝优化,能否想到优化,怎么样能够巧妙地根据不同一幕进行不同的优化,怎么优化就看题目啦。上代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=9;
char map[maxn][maxn];
int visit[maxn][maxn];
bool ans=0;
int n,m,t;
int abs(int x){
	return x>=0?x:-x;
}
void dfs(int x,int y,int time){
	if(ans) return;
	if(x-1>=0){
		if(visit[x-1][y]==3 && time==t){
			ans=1;
			return;
		}
		if(visit[x-1][y]==0){ 
			visit[x-1][y]=1;
			dfs(x-1,y,time+1);
			visit[x-1][y]=0;
		}
	}
	if(x+1<n){
		if(visit[x+1][y]==3 &&time==t){
			ans=1;
			return;
		}
		if(visit[x+1][y]==0){
			visit[x+1][y]=1;
			dfs(x+1,y,time+1);
			visit[x+1][y]=0;
		}
	}
	if(y-1>=0){
		if(visit[x][y-1]==3 && time==t){
			ans=1;
			return;
		}
		if(visit[x][y-1]==0){
			visit[x][y-1]=1;
			dfs(x,y-1,time+1);
			visit[x][y-1]=0;
		}
	}
	if(y+1<m){
		if(visit[x][y+1]==3 && time==t){
			ans=1;
			return;
		}
		if(visit[x][y+1]==0) {
			visit[x][y+1]=1;
			dfs(x,y+1,time+1);
			visit[x][y+1]=0;
		}
	}
	return;
}
int main(){
	while(cin>>n>>m>>t){
		if(n==0 && m==0 && t==0) break;
		int x,y,x2,y2,k1,k2;
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++){
				cin>>map[i][j];
				if(map[i][j]=='X')
					visit[i][j]=-1;
				else if(map[i][j]=='S'){
					visit[i][j]=2;
					k1=(i+j)%2;
					x=i;y=j;
				}
				else if(map[i][j]=='D'){
					visit[i][j]=3;
					x2=i;y2=j;
					k2=(i+j)%2;
				}
				else
					visit[i][j]=0;
			}
		k1=(k1+k2)%2;
		if((k1==0 && t%2==1)||(k1==1 && t%2==0)||(abs(x2-x)+abs(y2-y)>t)){
			cout<<"NO"<<endl;
			continue;
		}
		ans=0;
		dfs(x,y,1);
		if(ans)
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl;
		
	}
	return 0;
}
加油,好好学习,天天向上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值