hdu 1010 解题报告 ----Tempter of the Bone
题意:输入一个n*m的迷宫,和一个T:可以在迷宫中生存的最大时间。S为起点,D为终点。并且,每个格子只能踩一次,且只能维持一秒,然后该块地板就会塌陷。所以你必须每秒走一步,且到D点时,所用时间为T。用深搜。
本题要点:看是否能在所有可能的路中找到刚好满足条件(到达终点时门恰好打开)的路程,本题需要注意,单用深搜会超时,所以,有一个剪枝的地方非常重要!!!
本来写的是java版,但不知为何提交不了就还原陈了C++版
C++版:
Problem : 1010 ( Tempter of the Bone ) Judge Status : Accepted RunId : 8246601 Language : C++ Author : luotianyu520 Code Render Status : Rendered By HDOJ C++ Code Render Version 0.01 Beta #include<iostream> using namespace std; int sx,sy,ex,ey; //起点和终点坐标 int n,m; //迷宫的行数列数 char map[10][10];// 迷宫 int flag;//判断成功 int d[4][2]={0,1,1,0,0,-1,-1,0}; // 下、右、上、左 void dfs(int x,int y,int t) { /** 1、排除并剪枝 */ if(flag==1) return ;// 成功则返回 // 剩余时间不足以走到终点 或者 当前点与终点横纵坐标差的和 与 剩余时间之差奇偶性不同。则直接否决返回 if(t<abs(ex-x)+abs(ey-y)||(t-abs(ex-x)+abs(ey-y))%2) return ; // 时间用完,则判断是否到终点并返回 if(t==0) { if(x==ex&&y==ey) {flag=1; return ;} else { return ; } } /** 2、递归四个方向 */ for(int i=0;i<4;i++) { int nx=x+d[i][0],ny=y+d[i][1];//下一位置 // 排除:1越界,2不是'.'或不是终点 if (nx>0&&nx<=n&&ny>0&&ny<=m&&(map[nx][ny]=='.'||map[nx][ny]=='D')) { map[nx][ny]='X';//标记当前点走过 dfs( nx,ny,t-1) ;// 时间-1,递归下一点 map[nx][ny]='.';//还原状态 } } return ; } int main() { char str[10]; int t; while (scanf("%d%d%d",&n,&m,&t)!=EOF) { if(n==0&&m==0&&t==0) return 0; for (int i=1;i<=n;i++) { scanf("%s",str); for (int j=1;j<=m;j++) { map[i][j]=str[j-1]; if(map[i][j]=='S') sx=i,sy=j; else if(map[i][j]=='D') ex=i,ey=j; } } flag=0; dfs(sx,sy,t); if(flag==0) printf("NO\n"); else printf("YES\n"); } return 0; } #include<iostream> using namespace std; int sx,sy,ex,ey; //起点和终点坐标 int n,m; //迷宫的行数列数 char map[10][10];// 迷宫 int flag;//判断成功 int d[4][2]={0,1,1,0,0,-1,-1,0}; // 下、右、上、左 void dfs(int x,int y,int t) { /** 1、排除并剪枝 */ if(flag==1) return ;// 成功则返回 // 剩余时间不足以走到终点 或者 当前点与终点横纵坐标差的和 与 剩余时间之差奇偶性不同。则直接否决返回 if(t<abs(ex-x)+abs(ey-y)||(t-abs(ex-x)+abs(ey-y))%2) return ; // 时间用完,则判断是否到终点并返回 if(t==0) { if(x==ex&&y==ey) {flag=1; return ;} else { return ; } } /** 2、递归四个方向 */ for(int i=0;i<4;i++) { int nx=x+d[i][0],ny=y+d[i][1];//下一位置 // 排除:1越界,2不是'.'或不是终点 if (nx>0&&nx<=n&&ny>0&&ny<=m&&(map[nx][ny]=='.'||map[nx][ny]=='D')) { map[nx][ny]='X';//标记当前点走过 dfs( nx,ny,t-1) ;// 时间-1,递归下一点 map[nx][ny]='.';//还原状态 } } return ; } int main() { char str[10]; int t; while (scanf("%d%d%d",&n,&m,&t)!=EOF) { if(n==0&&m==0&&t==0) return 0; for (int i=1;i<=n;i++) { scanf("%s",str); for (int j=1;j<=m;j++) { map[i][j]=str[j-1]; if(map[i][j]=='S') sx=i,sy=j; else if(map[i][j]=='D') ex=i,ey=j; } } flag=0; dfs(sx,sy,t); if(flag==0) printf("NO\n"); else printf("YES\n"); } return 0; }
Java版(答案没问题,可惜就是不知道哪不对,若有人找到不胜感激):
package code.part3.problem; import java.util.Scanner; public class Main { static Scanner scanner = new Scanner(System.in); static int n, m, time;// 迷宫的行,列,时间 static char[][] map = new char[105][105];// 迷宫 static Point start = new Point(), end = new Point();// 起点、终点 static int[][] move = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };// 下、右、上、左 static boolean flag = false; private static class Point { int x; int y; } public static void main(String args[]) { while (scanner.hasNextInt()) { n = scanner.nextInt(); m = scanner.nextInt(); time = scanner.nextInt(); if (n <= 1 || m >= 7 || time >= 50) return; init(); dfs(start, time); if (flag) System.out.printf("YES\n"); else System.out.printf("NO\n"); } scanner.close(); } public static void init() { flag = false; for (int i = 0; i < n; i++) { map[i] = scanner.next().toCharArray(); for (int j = 0; j < m; j++) { if (map[i][j] == 'S') { start.x = i; start.y = j; } else if (map[i][j] == 'D') { end.x = i; end.y = j; } } } } public static void dfs(Point fromP, int time) { /** 1、排除并剪枝 */ // 成功则返回 if (flag) return; // 剩余时间不足以走到终点 或者 当前点与终点横纵坐标差的和 与 剩余时间之差奇偶性不同。则直接否决返回 if (time < Math.abs(end.x - fromP.x) + Math.abs(end.y - fromP.y) || (time - Math.abs(end.x - fromP.x) + Math .abs(end.y + fromP.y)) % 2 == 1) return; // 时间用完,则判断是否到终点并返回 if (time == 0) { if (fromP.x != end.x || fromP.y != end.y) return; flag = true; return; } /** 2、递归四个方向 */ for (int i = 0; i < 4; i++) { Point toP = new Point(); // 新位置 toP.x = fromP.x + move[i][0]; toP.y = fromP.y + move[i][1]; // 排除:1越界,2不是'.'或不是终点,直接下一个 if (toP.x < 0 || toP.y < 0 || toP.x >= n || toP.y >= m || (map[toP.x][toP.y] != '.' && map[toP.x][toP.y] != 'D')) continue; map[toP.x][toP.y] = 'X';// 标记当前点走过 dfs(toP, time - 1);// 时间-1,递归下一点 map[toP.x][toP.y] = '.';// 还原状态 } } }