狼蛛 - Tarantula - Dijkstra

狼蛛

时限:最多 40 个用例,1.5 秒 (C/C++),2 秒 (Java)

当前有一个N行M列大小的二维网格型迷宫。假设左上角格子的坐标是[1, 1],右下角格子的坐标是[N, M]。你目前在 [1, 1] 格子上。在 [N, M] 格子有个出口,可以逃出网格迷宫。在网格内只能以上下左右四个方向移动。

这个网格迷宫中有狼蛛,如果被狼蛛咬到,那么肢体会无力或丧失意识,导致逃出网格迷宫会很困难。幸运的是,狼蛛数量并不多,所以在每个格子中碰不到狼蛛的可能性很高,概率在99.99% 到 100% 之间。

如图1所示,假设有一个迷宫,每个格子给出了碰不到狼蛛的概率。

 

 

(图 1)

这时,碰不到狼蛛的概率(%)的小数点后第三位开始的值将定义为 P,P 为介于 0 到 100 之间的整数,这也是跟每个格子中写的大数字相关。(100 表示 100% 的概率。)

 

 

(图 2)

如果按照图2左边所示的橙色路线移动时,碰不到狼蛛而逃出迷宫的概率为 99.9990% * 99.9997% * 99.9950% * 99.9996% * 99.9990% = 99.9923%。如果按照右边所示的绿色路线移动时,碰不到狼蛛而安全逃出迷宫的概率为 99.9990% * 99.9960% * 99.9998% * 99.9996% * 99.9990% = 99.9934%,而这是没有碰到狼蛛而最安全的逃出迷宫的概率

当每个格子中给出碰不到狼蛛的概率时,从[1, 1]位置出发到达[N, M]位置后,请求出通过出口逃出迷宫为止,不碰到狼蛛可以最安全的逃出迷宫的概率

[限制条件]

  1. 二维网格的行数 N 和列数 M 是介于 1 到 300 之间的整数。
  2. P是碰不到狼蛛的概率的小数点后第三位开始的数值,是介于 0 到 100 之间的整数。
    (0表示碰不到狼蛛的概率为 99.9900%,1表示碰不到狼蛛的概率为 99.9901%,… 100 表示概率为 100%。)
  3. 在[1, 1] 和 [N, M]位置上也可能会碰到狼蛛。

[输入]

首先给出测试用例数量T,然后给出T种测试用例。每个测试用例的第一行空格区分给出二维网格的大小N,M。接下来通过N行,每行空格区分给出M个从各位置移动到另一个格子时碰不到狼蛛的概率(P)值。

[输出]

一个测试用例输出一行。每个测试用例都输出“#x”(其中x表示测试用例编号,从 1 开始),然后输出不碰到狼蛛逃出迷宫的最高概率(精确到小数点后6位,在第7位数四舍五入)例如,答案为 0.9999002的情况,输出为 0.999900,不省略0。

[输入输出 案例]

(输入)

2
3 3
90 60 98
97 50 96
85 40 90
6 4
10 50 30 20
90 99 77 88
27 50 33 99
5 73 99 99
4 21 98 40
9 59 99 100

(输出)

#1 0.999934
#2 0.999858

 

思路: Dijkstra

 

package pro.dijkstra;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

/**
 * Dijkstra
 * @author XA-GDD
 *
 */
public class Tarantula_0315 {
	static int T,N,M;
	static TarantulaNode [][] prob = new TarantulaNode [302][302];
	static int [][] dire = new int [][] {{-1,0},{0,1},{1,0},{0,-1}}; //移动方向
	static double num = 1000000;
	static double ANS;

	public static void main(String[] args) throws IOException {
		System.setIn(new FileInputStream("D:\\workspace\\sw_pro\\test_case\\sample_input_0315.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		T = Integer.parseInt(st.nextToken());
		for(int testCase=1;testCase<=T;testCase++) {
			st = new StringTokenizer(br.readLine());
			N = Integer.parseInt(st.nextToken());
			M = Integer.parseInt(st.nextToken());
			for(int i=1;i<=N;i++) {
				st = new StringTokenizer(br.readLine());
				for(int j=1;j<=M;j++) {
					int val = Integer.parseInt(st.nextToken());
					//此处一直要相除,勿直接拼接
					double probVal = 0.9999+(double)val/num; 
					prob[i][j] = new TarantulaNode(i,j,probVal);
				}	
			}
			ANS =  dijkstra(prob[1][1]);
			System.out.printf("#%d %.6f\n",testCase,ANS);
			
		}

	}
	
	static double dijkstra(TarantulaNode start) {
		PriorityQueue<TarantulaNode> pq = new PriorityQueue<TarantulaNode>(new Comparator<TarantulaNode>() {
			@Override
			public int compare(TarantulaNode o1, TarantulaNode o2) {
				if(o2.maxProb>o1.maxProb) {
					return 1;
				}else {
					return -1;
				}
			}
		});
		
		start.maxProb = start.prob;
		pq.add(start);
		
		TarantulaNode curr;
		TarantulaNode next;
		while(!pq.isEmpty()) {
			curr = pq.poll();
			if(curr.visited==1) {
				continue;
			}
			curr.visited=1;
			for(int i=0;i<4;i++) {
				int x = curr.x + dire[i][0];
				int y = curr.y + dire[i][1];
				if(!isValid(x,y)) {
					continue;
				}
				next = prob[x][y];
				if(next.maxProb < curr.maxProb*next.prob) {
					next.maxProb=curr.maxProb*next.prob;	
					pq.add(next);					
				}
			}
		}
		return prob[N][M].maxProb;
	}
	
	static boolean isValid(int x, int y) {
		return x>0 && x<=N && y>0 && y<=M;
	}
}

class TarantulaNode{
	int x;
	int y;
	int visited;
	double prob;
	double maxProb;
	TarantulaNode(int x,int y, double prob){
		this.x = x;
		this.y = y;
		this.prob = prob;
		this.visited = 0;
	}
}

  

posted @ 2022-01-20 20:59  晓暮云  阅读(397)  评论(0编辑  收藏  举报