先上原题链接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没太大的区别,只是多了一个搜索区域,可以经过“传送门”在其之间跳转而已,把握好各变量间的关系以及关键的判断条件,不要昏了头就行了。