【题解】HDU2102 A计划

先上原题链接http://hdu.hustoj.com/showproblem.php?pid=2102

嘛,虽然不是很难的题,但是是值得庆祝正式回归HDU的第一道复健题(题目还槽点满满的),原题如下:

A计划

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

Problem Description
可怜的公主在一次次被魔王掳走一次次被骑士们救回来之后,而今,不幸的她再一次面临生命的考验。魔王已经发出消息说将在T时刻吃掉公主,因为他听信谣言说吃公主的肉也能长生不老。年迈的国王正是心急如焚,告招天下勇士来拯救公主。不过公主早已习以为常,她深信智勇的骑士LJ肯定能将她救出。
现据密探所报,公主被关在一个两层的迷宫里,迷宫的入口是S(0,0,0),公主的位置用P表示,时空传输机用#表示,墙用*表示,平地用.表示。骑士们一进入时空传输机就会被转到另一层的相对位置,但如果被转到的位置是墙的话,那骑士们就会被撞死。骑士们在一层中只能前后左右移动,每移动一格花1时刻。层间的移动只能通过时空传输机,且不需要任何时间。

Input
输入的第一行C表示共有C个测试数据,每个测试数据的前一行有三个整数N,M,T。 N,M迷宫的大小NM(1 <= N,M <=10)。T如上所意。接下去的前NM表示迷宫的第一层的布置情况,后N*M表示迷宫第二层的布置情况。

Output
如果骑士们能够在T时刻能找到公主就输出“YES”,否则输出“NO”。

Sample Input
1
5 5 14
S*#*.
.#…

****.
…#.

.P
#.

**
.
*.#…

Sample Output
YES

看完题目我就忍不住要吐槽了——“她深信智勇的骑士LJ(垃圾)肯定能将她救出”可还行,然后就是这道题几个坑点:
1、题目中并没有说P只能在第二层,留意公主被关押在第一层的情况
2、想想传送门的对面是个墙会怎么办(LJ骑士卒)
3、那么既然传送门的对面可以是个墙,那要是也还是个传送门呢。。。。(LJ骑士成为了空间夹缝中的碎片,Game over,这大概是我见过的最机智的魔王吧,学到了)

其他的话,就没什么困难的地方了,数据量也不是很大,DFS莽…还是要稍微做下优化的,可以看到,题目中是有时间限制的,那么当耗时超过了这一限制以后,我们就可以直接跳出搜索,这也是搜索中最常用的剪枝方法之一

以下是AC代码:

import java.util.Scanner;

public class Main{
	
	static char room1[][] = new char [15][15];		 //迷宫第一层
	static char room2[][] = new char[15][15]; 		//迷宫第二层
	static int n = 0,m = 0;			
	static int t = 0,T = 0;				
	static boolean f = false;			//记录是否救出公主的flag
	
	public static void main(String args[]){
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		while(t -- >0){
			n = sc.nextInt();
			m = sc.nextInt();
			T = sc.nextInt();
			for(int i = 0;i < n;i++)
				room1[i] = sc.next().toCharArray();
			for(int i = 0;i < n;i++)
				room2[i] = sc.next().toCharArray();
			dfs1(0,0);
			if(f)System.out.println("YES");
			else System.out.println("NO");
			f = false;
			Main.t = 0;
		}
	}
	
	public static void dfs1(int x,int y){
		if(f||x<0||x>=n||y<0||y>=m||room1[x][y] == '*'||t >T)return;
		else{
			if(room1[x][y] == 'P'){
				f = true;
				return;
			}
			if(room1[x][y]=='#'){
				if(room2[x][y] == '#' || room2[x][y] == '*')return;
				dfs2(x,y);
				return;
			}
			else{
				t++;
				room1[x][y] = '*';
				dfs1(x-1,y);
				dfs1(x+1,y);
				dfs1(x,y+1);
				dfs1(x,y-1);
				room1[x][y] = '.';
				t--;
				return;
			}
		}
	} 
	
	public static void dfs2(int x,int y){
		if(f||x<0||x>=n||y<0||y>=m||room2[x][y] == '*'||t >T)return;
		else{
			if(room2[x][y]=='P'){
				f = true;
				return;
			}
			if(room2[x][y]=='#'){
				if(room1[x][y] == '#' || room1[x][y] == '*')return;
				dfs1(x,y);
				return;
			}
			else{
				t++;
				room2[x][y] = '*';
				dfs2(x-1,y);
				dfs2(x+1,y);
				dfs2(x,y+1);
				dfs2(x,y-1);
				room2[x][y] = '.';
				t--;
				return;
			}
		}
	}
	
}

代码的思路和一般的DFS没太大的区别,只是多了一个搜索区域,可以经过“传送门”在其之间跳转而已,把握好各变量间的关系以及关键的判断条件,不要昏了头就行了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值