【搜索】B039_openj_拯救唐僧(PQ + SC)

一、Problem

《西遊記》是中國文學四大經典小說之一。 它是明代吳承恩寫的。 在這部小說中,孫悟空、豬豬八戒和沙僧護送唐僧到印度獲取佛教文本。

在旅途中,唐僧經常被惡魔俘虜。 大多數惡魔都想吃唐僧才能長生不老,但有些女惡魔只是想嫁給他,因爲他很帥。 所以,對抗惡魔和拯救蒙唐是孫悟空的主要工作。

有一次,唐僧被惡魔白骨捕獲。 白骨住在一座宮殿裏,她把唐僧銬在一個房間裏。 孫悟空設法進了皇宮… 但要拯救唐僧,孫悟空可能需要得到一些鑰匙,並殺死蛇的方式。

宮殿可以被描述爲一個人物的矩陣。 每個角色代表一個房間。在矩陣中,‘K’代表孫悟空的原始位置,‘T’代表唐僧的位置,‘S’代表一個有蛇的房間。 請注意,宮殿裏只有一條“K”和一條“T”,最多有五條蛇。 ‘.’ 意思是一個乾淨的房間,以及 ‘#’ 意味着一個致命的房間,孫悟空無法進入。

房間裏可能會有一些不同種類的鑰匙散落在房間裏,一個房間裏最多隻有一把鑰匙。 最多有9種鑰匙。 有鑰匙的房間用一個數字(從‘1’到‘9’)表示。 例如,“1”是指帶有第一類鑰匙的房間,“2”是指帶有第二類鑰匙的房間,“3”是指帶有第三類鑰匙的房間…等等。 爲了拯救唐僧,孫悟空必須得到各種鑰匙(換句話說,每種至少有一個鑰匙)。

每一步,孫悟空都可以向四個方向(北、西、南、東)移動到相鄰的房間(致命的房間除外),每一步都花了他一分鐘。如果他進入了一個潛逃的房間,他必須殺死蛇。 殺死一條蛇也花了一分鐘。 如果孫悟空進入一個房間,那裏有一個類型N的鑰匙,孫會得到這個鑰匙,前提是當他已經有類型 1,類型 2 和類型 N-1 的鑰匙。 如果孫悟空得到了他所需要的所有鑰匙,進入唐僧被銬住的房間,救援任務就完成了。 如果孫悟空沒有得到足夠的鑰匙,他仍然可以通過唐僧的房間。孫悟空是一隻不耐煩的猴子,他想盡快救唐僧。 請找出孫悟空救唐僧所需的最短時間。

輸入

For each case, the first line includes two integers N and M(0 < N <= 100, 0<=M<=9), meaning that the palace is a N×N matrix and Sun Wukong needed M kinds of keys(kind 1, kind 2, … kind M).

Then the N×N matrix follows. The input ends with N = 0 and M = 0.

輸出

For each test case, print the minimum time (in minutes) Sun Wukong needed to save Tang Monk. If it’s impossible for Sun Wukong to complete the mission, print “impossible”(no quotes).

3 1
K.S
##1
1#T
3 1
K#T
.S#
1#.
3 2
K#T
.S.
21.
0 0
 
5
impossible
8

二、Solution

題意爲一個地圖,‘K’代表孫悟空的位置,也就是起點,‘T’代表唐僧的位置,數字‘1’‘2’等代表鑰匙類型,‘S’ 代表蛇,’#’ 不能走,題意的目的就是孫悟空去救唐僧,要求前提必須是拿到給定的 m 種鑰匙,才能去救唐僧,除了 '#‘ 的位置,其他位置都可以走(如果到達了唐僧的位置,但沒拿到給定的 m 種鑰匙,任務也沒法完成,必須得拿到 m 鍾鑰匙)。到達 ‘S’ 位置,要多花一分鐘殺死蛇,其他位置走一步花一分鐘,問最少花多少分鐘才能解救唐僧,如果不能,輸出impossible.

方法一:bfs + SC

本題難點:

  • Q1:如何標記蛇精已經殺死還是沒死?
    A1:使用 5 個二進制位即可。
  • Q2:題目說道師傅的房間可經過多次,你怎麼知道經過的就是最短?
    A2:只要鑰匙收集夠了,第一次經過就是最短。

未知錯誤:也不知道哪裏寫不對…

import java.util.*;
import java.math.*;
import java.io.*;
public class Main {
	static int N, M;
	static char[][] grid;
	final static int[][] dir = { {1,0},{0,-1},{0,1},{-1,0} };
	static boolean[][][][] vis;
	static int sx, sy;
	static int INF = 0x3f3f3f3f;
	
	private static boolean inArea(int x, int y) {
		return x >= 0 && x < N && y >= 0 && y < N;
	}
    public static void main(String[] args) throws IOException {  
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
		while (true) {
			N = sc.nextInt();
			M = sc.nextInt();
			if (N == 0 && M == 0)
				break;
			grid = new char[N][N];
			vis = new boolean[N][N][1<<5 + 1][10];	//5條蛇 9把鑰匙
			int snake = 0;
			for (int i = 0; i < N; i++) {
				String s = sc.next();
				for (int j = 0; j < N; j++) {
					grid[i][j] = s.charAt(j);
					if (grid[i][j] == 'K') {
						sx = i; sy = j;
					} else if (grid[i][j] == 'S') {
						grid[i][j] = (char) ('a' + snake);
						snake++;
					}
				}
			}
			bfs();
			System.out.println(res == INF ? "impossible" : res);
			res = INF;
		}
    }
	static int res = INF;
	private static void bfs() {
		Queue<Pos> q = new PriorityQueue<>((e1, e2) -> e1.d - e2.d);
		q.add(new Pos(sx, sy, 0, 0, 0));
		vis[sx][sy][0][0] = true;
		
		while (!q.isEmpty()) {
			Pos t = q.poll();
			if (t.k == M && grid[t.x][t.y] == 'T') {
				res = t.d;
				return;
			}
			for (int i = 0; i < 4; i++) {
				int tx = t.x + dir[i][0];
				int ty = t.y + dir[i][1];
				if (!inArea(tx, ty) || grid[tx][ty] == '#')
					continue;
				
				if ('1' <= grid[tx][ty] && grid[tx][ty] <= '9') {		 	//鑰匙
					t.d++;
					int id = grid[tx][ty] - '0';
					if (t.k + 1 == id)
						t.k++;
				} else if ('a' <= grid[tx][ty] && grid[tx][ty] <= 'z') {	//蛇
					int id = grid[tx][ty] - 'a';
					if ((t.s & (1 << id)) == 1) {		//死
						t.d+=1;
					} else {
						t.d+=2;
					}
					t.s |= (1 << id);
				} else {
					t.d++;
				}
				if (!vis[tx][ty][t.s][t.k]) {
					vis[tx][ty][t.s][t.k] = true;
					q.add(new Pos(tx, ty, t.d, t.s, t.k));
				}
			}
		}
	}
	static class Pos {
		int x, y, d, k, s;
		Pos(int _x, int _y, int _d, int _s, int _k) {
		   x = _x;y = _y;d = _d;k = _k;s = _s;
		}
	}
}	

複雜度分析

  • 時間複雜度:O()O()
  • 空間複雜度:O()O()

適當剪枝:

  • 用一個 int[][][][] dist 來記錄每一步的信息,如果點.時,如果當前步數比該點的步數還要多,那麼不更新該位置的 dist。

有時間再看看…
https://blog.csdn.net/sr_19930829/article/details/40352719
這裏

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章