解题报告:hdu1242 zoj1649 Rescue
2012-08-17 23:57
381 查看
解题报告:hdu1242 zoj1649
Rescue
Time Limit: 2 Seconds Memory Limit: 65536 KB
Angel was caught by the MOLIGPY! He was put in prison by Moligpy.
The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison.
Angel's friends want to save Angel. Their task is: approach Angel.
We assume that "approach Angel" is to get to the position where Angel stays.
When there's a guard in the grid, we must kill him (or her?) to move into the grid.
We assume that we moving up, down, right, left takes us 1 unit time, and killing a guard takes 1 unit time, too.
And we are strong enough to kill all the guards.
You have to calculate the minimal time to approach Angel.
(We can move only UP, DOWN, LEFT and RIGHT, to the neighbor grid within bound, of course.)
Input
First line contains two integers stand for N and M.
Then N lines follows, every line has M characters. "." stands for road, "a" stands for Angel,
and "r" stands for each of Angel's friend.
Process to the end of the file.
Output
For each test case, your program should output a single integer,
standing for the minimal time needed. If such a number does no exist,
you should output a line containing "Poor ANGEL has to stay in the prison all his life."
Sample Input
7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........
Sample Output
13
题意:在n×m的棋盘似的图形中,求从r到a的最短时间,但要注意不止一个r,
如果遇到“.”的话就消耗一个单位的时间,遇到“x”消耗两个单位的时间,
遇到“#”的话,不能继续前行。
分析:显然这个题目就是求从各个r到达a的最短路径,不过要对于特殊情况进行特判。这样其实有两种做法,第一种就是从r出发找a,这样
其实可以使用dfs(详细见代码一),不过这种做法显然不算优,代码一在hdu可以AC,但是到zoj就是TLE,看来这个方法有点赖过去的嫌疑。
方法二更加优越,从a出发,逆向思维,直到找到第一个r为止(这样说不准确,应该是用时最少的r)。(见代码二)
代码一:
import java.util.Scanner;
public class Main {
static int INF = 1000000000;
static int n, m, time, ax, ay, ex, ey;//time其实就是记录最小用时,ax,ay为r所在的位置,ex,ey为a所在的位置
static int[][] map = new int[205][205];//记录的是从r出发到达(i,j)的最小用时
static int[][] dis = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };//记录可以移动的四个方向
static int[][] visited = new int[205][205];//标记从上个点移动到(i,j)这个点这一个移动消耗的时间
static int dfs(int x, int y, int t) {
int i, ch, xn, yn;
if (x == ex && y == ey) {//如果这时已经找到a,递归结束
if (t < time)
time = t;
return 0;
} else {
for (i = 0; i < 4; ++i) {//从(x,y)出发,向四个方向移动
xn = x + dis[i][0];
yn = y + dis[i][1];
if (xn < 0 || xn >= n || yn < 0 || yn >= m)//这一步很重要
continue;
if ((visited[xn][yn] == 1 || visited[xn][yn] == 2)//询问这个节点是否合法,且是否用时更少
&& t + visited[xn][yn] <= time) {
if (map[xn][yn] == -1 || t + visited[xn][yn] <= map[xn][yn]) {
map[xn][yn] = t + visited[xn][yn];
ch = visited[xn][yn];//保存下visited[xn][yn]的值
visited[xn][yn] = -1;//更改visited[xn][yn]保证在下面的递归过程中,不能在往回走
dfs(xn, yn, t + ch);
visited[xn][yn] = ch;//将visited[xn][yn]这个值进行还原,因为可能在下面的运行过程中还有可能用到
//也就是因为可能一条路线可能会被多次查询,所以才有可能会TLE
}
}
}
}
return 0;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
char[] str = new char[203];
while (scan.hasNext()) {
time = INF;
n = scan.nextInt();
m = scan.nextInt();
//初始化
for (int i = 0; i <= n + 2; i++) {
for (int j = 0; j <= m + 2; j++) {
map[i][j] = -1;
visited[i][j] = -1;
}
}
//读入这个图形,同时找到ax,ay,ex,ey,对visited数组进行合法化初始化
for (int i = 0; i < n; i++) {
String st = scan.next();
str = st.toCharArray();
for (int j = 0; j < m; j++) {
if (str[j] == '.')
visited[i][j] = 1;
else if (str[j] == 'x')
visited[i][j] = 2;
else if (str[j] == 'r') {
ax = i;
ay = j;
} else if (str[j] == 'a') {
ex = i;
ey = j;
visited[i][j] = 1;
}
}
}
dfs(ax, ay, 0);
if (time != INF)
System.out.println(time);
else
System.out
.println("Poor ANGEL has to stay in the prison all his life.");
}
}
}
代码二
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;
class point {
int x, y, step;//定义一个顶点类,坐标为(x,y),用step表示到达该节点
}
public class Mainhdu1242 {
static int n, m, bx, by;
static char[][] map = new char[202][202];//记录每个点的状态
static int[][] dis = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
static void bfs() {
PriorityQueue<point> queue = new PriorityQueue<point>(1,//用到了优先队列,把每个结点用step进行排序
new Comparator<point>() {
public int compare(point a, point b) {
if (a.step < b.step)
return -1;
else if (a.step == b.step) {
return 0;
} else {
return 1;
}
}
});
point t = new point();
t.x = bx;
t.y = by;
t.step = 0;
queue.offer(t);
while (!queue.isEmpty()) {
point q = queue.poll();
for (int i = 0; i < 4; i++) {
point tt = new point();//注意不能直接写成point tt=q,应为这样传递的是指针,在改变tt的参数的同时也改变了q
tt.x = q.x + dis[i][0];
tt.y = q.y + dis[i][1];
tt.step = q.step + 1;
i
8af6
f (tt.x < 0 || tt.x >= n || tt.y < 0 || tt.y >= m
|| map[tt.x][tt.y] == '#')
continue;
else if (map[tt.x][tt.y] == 'r') {
System.out.println(tt.step);
return;
} else if (map[tt.x][tt.y] == 'x')
tt.step++;
map[tt.x][tt.y] = '#';//将查询过的点标记为不能再次查询
queue.offer(tt);//把查询到的点加到队列中
}
}
System.out
.println("Poor ANGEL has to stay in the prison all his life.");
return;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while (scan.hasNext()) {
n = scan.nextInt();
m = scan.nextInt();
for (int i = 0; i < n; i++) {
String str = scan.next();
map[i] = str.toCharArray();
for (int j = 0; j < m; j++) {
if (map[i][j] == 'a') {
bx = i;
by = j;
break;
}
}
}
bfs();
}
}
}
Rescue
Time Limit: 2 Seconds Memory Limit: 65536 KB
Angel was caught by the MOLIGPY! He was put in prison by Moligpy.
The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison.
Angel's friends want to save Angel. Their task is: approach Angel.
We assume that "approach Angel" is to get to the position where Angel stays.
When there's a guard in the grid, we must kill him (or her?) to move into the grid.
We assume that we moving up, down, right, left takes us 1 unit time, and killing a guard takes 1 unit time, too.
And we are strong enough to kill all the guards.
You have to calculate the minimal time to approach Angel.
(We can move only UP, DOWN, LEFT and RIGHT, to the neighbor grid within bound, of course.)
Input
First line contains two integers stand for N and M.
Then N lines follows, every line has M characters. "." stands for road, "a" stands for Angel,
and "r" stands for each of Angel's friend.
Process to the end of the file.
Output
For each test case, your program should output a single integer,
standing for the minimal time needed. If such a number does no exist,
you should output a line containing "Poor ANGEL has to stay in the prison all his life."
Sample Input
7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........
Sample Output
13
题意:在n×m的棋盘似的图形中,求从r到a的最短时间,但要注意不止一个r,
如果遇到“.”的话就消耗一个单位的时间,遇到“x”消耗两个单位的时间,
遇到“#”的话,不能继续前行。
分析:显然这个题目就是求从各个r到达a的最短路径,不过要对于特殊情况进行特判。这样其实有两种做法,第一种就是从r出发找a,这样
其实可以使用dfs(详细见代码一),不过这种做法显然不算优,代码一在hdu可以AC,但是到zoj就是TLE,看来这个方法有点赖过去的嫌疑。
方法二更加优越,从a出发,逆向思维,直到找到第一个r为止(这样说不准确,应该是用时最少的r)。(见代码二)
代码一:
import java.util.Scanner;
public class Main {
static int INF = 1000000000;
static int n, m, time, ax, ay, ex, ey;//time其实就是记录最小用时,ax,ay为r所在的位置,ex,ey为a所在的位置
static int[][] map = new int[205][205];//记录的是从r出发到达(i,j)的最小用时
static int[][] dis = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };//记录可以移动的四个方向
static int[][] visited = new int[205][205];//标记从上个点移动到(i,j)这个点这一个移动消耗的时间
static int dfs(int x, int y, int t) {
int i, ch, xn, yn;
if (x == ex && y == ey) {//如果这时已经找到a,递归结束
if (t < time)
time = t;
return 0;
} else {
for (i = 0; i < 4; ++i) {//从(x,y)出发,向四个方向移动
xn = x + dis[i][0];
yn = y + dis[i][1];
if (xn < 0 || xn >= n || yn < 0 || yn >= m)//这一步很重要
continue;
if ((visited[xn][yn] == 1 || visited[xn][yn] == 2)//询问这个节点是否合法,且是否用时更少
&& t + visited[xn][yn] <= time) {
if (map[xn][yn] == -1 || t + visited[xn][yn] <= map[xn][yn]) {
map[xn][yn] = t + visited[xn][yn];
ch = visited[xn][yn];//保存下visited[xn][yn]的值
visited[xn][yn] = -1;//更改visited[xn][yn]保证在下面的递归过程中,不能在往回走
dfs(xn, yn, t + ch);
visited[xn][yn] = ch;//将visited[xn][yn]这个值进行还原,因为可能在下面的运行过程中还有可能用到
//也就是因为可能一条路线可能会被多次查询,所以才有可能会TLE
}
}
}
}
return 0;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
char[] str = new char[203];
while (scan.hasNext()) {
time = INF;
n = scan.nextInt();
m = scan.nextInt();
//初始化
for (int i = 0; i <= n + 2; i++) {
for (int j = 0; j <= m + 2; j++) {
map[i][j] = -1;
visited[i][j] = -1;
}
}
//读入这个图形,同时找到ax,ay,ex,ey,对visited数组进行合法化初始化
for (int i = 0; i < n; i++) {
String st = scan.next();
str = st.toCharArray();
for (int j = 0; j < m; j++) {
if (str[j] == '.')
visited[i][j] = 1;
else if (str[j] == 'x')
visited[i][j] = 2;
else if (str[j] == 'r') {
ax = i;
ay = j;
} else if (str[j] == 'a') {
ex = i;
ey = j;
visited[i][j] = 1;
}
}
}
dfs(ax, ay, 0);
if (time != INF)
System.out.println(time);
else
System.out
.println("Poor ANGEL has to stay in the prison all his life.");
}
}
}
代码二
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;
class point {
int x, y, step;//定义一个顶点类,坐标为(x,y),用step表示到达该节点
}
public class Mainhdu1242 {
static int n, m, bx, by;
static char[][] map = new char[202][202];//记录每个点的状态
static int[][] dis = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
static void bfs() {
PriorityQueue<point> queue = new PriorityQueue<point>(1,//用到了优先队列,把每个结点用step进行排序
new Comparator<point>() {
public int compare(point a, point b) {
if (a.step < b.step)
return -1;
else if (a.step == b.step) {
return 0;
} else {
return 1;
}
}
});
point t = new point();
t.x = bx;
t.y = by;
t.step = 0;
queue.offer(t);
while (!queue.isEmpty()) {
point q = queue.poll();
for (int i = 0; i < 4; i++) {
point tt = new point();//注意不能直接写成point tt=q,应为这样传递的是指针,在改变tt的参数的同时也改变了q
tt.x = q.x + dis[i][0];
tt.y = q.y + dis[i][1];
tt.step = q.step + 1;
i
8af6
f (tt.x < 0 || tt.x >= n || tt.y < 0 || tt.y >= m
|| map[tt.x][tt.y] == '#')
continue;
else if (map[tt.x][tt.y] == 'r') {
System.out.println(tt.step);
return;
} else if (map[tt.x][tt.y] == 'x')
tt.step++;
map[tt.x][tt.y] = '#';//将查询过的点标记为不能再次查询
queue.offer(tt);//把查询到的点加到队列中
}
}
System.out
.println("Poor ANGEL has to stay in the prison all his life.");
return;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while (scan.hasNext()) {
n = scan.nextInt();
m = scan.nextInt();
for (int i = 0; i < n; i++) {
String str = scan.next();
map[i] = str.toCharArray();
for (int j = 0; j < m; j++) {
if (map[i][j] == 'a') {
bx = i;
by = j;
break;
}
}
}
bfs();
}
}
}
相关文章推荐
- HDU1242 Rescue 解题报告--bfs
- hdu 1242 Rescue bfs+优先队列 解题报告
- hdu 1242 Rescue 解题报告
- hdu 5759 2016 Multi-University Training Contest 3 Gardener Bo 解题报告
- HDU - 1421 搬寝室 解题报告
- hdu 2073 无限的路 解题报告
- hdu 2037 今年暑假不AC 解题报告
- HDU 解题报告索引
- HDU 4864 Task (2014多校联合训练第一场1004) 解题报告(贪心)
- HDU 3509解题报告
- HDU 2254解题报告
- HDU1789 解题报告
- 解题报告:HDU 5763
- BestCoder4 1002 Miaomiao's Geometry (hdu 4932) 解题报告
- HDU 4576 Robot 解题报告(循环矩阵)
- HDU 1232 - 并查集 解题报告
- HDU 3549 Flow Problem 解题报告(EK)算法
- HDU 1.1.5解题报告
- HDU2028(解题报告)
- hdu 4527 小明系列故事——玩转十滴水 bfs 解题报告