[第一場(2)]portal

題目描述
這次題目的主角Chell必須解決GLaDOS提出的一個新的難題。Chell現在在一個佈局可以表示爲N行M列的房間當中,每一個細分的方格中,可以是一下幾種情況之一: ·障礙物-牆(表示爲‘#’) ·Chell最初始的位置(表示爲‘C’) ·Chell必須到達的終點(表示爲‘F’) ·空位置(表示爲‘.’) Chell手上有一門所謂的“門槍”,這把槍可以在牆上創造一個入口,每次移動時,她可以進行以下操作中的一種操作: ·向上、下、左、右移動到相鄰區域(無法移動到有牆的區域) ·如果上、下、左、右方向有一堵牆(不是相鄰的上下左右方向),則可以使用“門槍”在牆上創造一個入口,這個入口只能從被激活的這一側進入,同一時刻最多隻可激活兩個入口。如果在已經存在兩個入口時再激活一個入口,那麼,先創建的那個入口就會消失。創造這種入口所消耗的時間可忽略不計,即記爲消耗0時間。 ·如果Chell在一個與牆壁相鄰的位置,且這個牆面向她的這一側有一個入口,且現在有兩個入口,那麼Chell就可以通過這個入口到另一個入口前的一個無障礙位置。此移動持續一個單位時間。 Chell想知道,她最少需要花費多少時間,從起點到終點。 注意:房間兩側總有牆壁,字母‘C’和‘F’只會出現一次。
輸入格式
第一行輸入兩個正整數N、M(4≤N,M≤500),表示房間的行列數。 接下來輸入一個N行M列的地圖,每個格子包含‘C’,‘.’,‘F’,‘#’這四種中的一種字符。
輸出格式
輸出Chell從起點到終點最少需要花費的時間,如果她不能到達終點,則輸出“nemoguce”。
樣例
樣例輸入1

4 4

#.F#
#C.#

樣例輸出1

2
樣例輸入2

6 8
########
#.##…F#
#C.##…#
#…#…#
#…##
########
樣例輸出2

4
樣例輸入3

4 5

#C#.#
###F#

樣例輸出3

nemoguce
數據範圍與提示
對於樣例2,首先在起點的左側(3,1)和下側(6,2)建立一個入口,那麼,消耗1個單位時間,Chell就可以到達(5,2)。到達(5,2)後,再在右邊(5,7)的牆上建立一個入口,此時,存在的兩個入口分別在(6,2)和(5,7)這兩個位置,再通過1個單位時間到達(5,6)這個位置。同理,在往上(1,6)建立一個入口,再通過入口,從(5,6)到達(2,6),再向右一步到達終點。這當中一共消耗了4個單位時間。

解題思路

此題就是走迷宮,只不過在靠牆的地方的時候我們可以四個方向一直走到底。
我們考慮一個點,它與四個方向的牆的距離我們可以求出來,然後它到四個牆所需時間就是它到離他最近的牆的距離,我們連個邊,建個圖,進行最短路操作。

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
struct node{
	int u,v;
	node(){};
	node(int U,int V){
		u = U,v = V;
	}
};
int n,m,s,e,dis[250005];
char mase[505][505];
bool vis[250005];
vector <node>G[250005];
void spfa(){
	memset(dis,0x3f,sizeof(dis));
	dis[s] = 0;
	queue<int>Q;
	Q.push(s);
	vis[s] = 1;
	while (!Q.empty()){
		int p = Q.front();
		Q.pop();
		vis[p] = 0;
		int xx = G[p].size();
		for (int i = 0;i < xx;i ++){
			int u = G[p][i].u,v = G[p][i].v;
			if (dis[u] > dis[p] + v){
				dis[u] = dis[p] + v;
				if (!vis[u]){
					Q.push(u);
					vis[u] = 1;
				}
			}
		}
	}
	if (dis[e] == 0x3f3f3f3f)
		printf("nemoguce\n");
	else 	
		printf("%d",dis[e]);
}
int main(){
	scanf ("%d%d",&n,&m);
	for (int i = 1;i <= n;i ++){
		scanf("\n");
		for (int j = 1;j <= m;j ++){
			scanf ("%c",&mase[i][j]);
			if (mase[i][j] == 'C'){
				mase[i][j] = '.';
				s = i * m + j;
			}
			if (mase[i][j] == 'F'){
				mase[i][j] = '.';
				e = i * m + j;
			}
		}
	}
	for (int i = 1;i <= n;i ++){
		for (int j = 1;j <= m;j ++){
			if (mase[i][j] == '#')
				continue;
			if (j + 1 <= m && mase[i][j + 1] != '#'){
				G[i * m + j].push_back(node(i * m + j + 1,1));
				G[i * m + j + 1].push_back(node(i * m + j,1));
			}
			if (i + 1 <= n && mase[i + 1][j] != '#'){
				G[(i + 1) * m + j].push_back(node(i * m + j,1));
				G[i * m + j].push_back(node((i + 1) * m + j,1));
			}
			int tot1 = 0,k1 = i - 1;
			while (mase[k1][j] != '#'){
				k1 --;
				tot1 ++;
			}
			int tot2 = 0,k2 = i + 1;
			while (mase[k2][j] != '#'){
				k2 ++;
				tot2 ++;
			}
			int tot3 = 0,k3 = j - 1;
			while (mase[i][k3] != '#'){
				k3 --;
				tot3 ++;
			}
			int tot4 = 0,k4 = j + 1;
			while (mase[i][k4] != '#'){
				k4 ++;
				tot4 ++;
			}
			int min_tot = min(tot1,min(tot2,min(tot4,tot3))) + 1;
			G[i * m + j].push_back(node ((k1 + 1) * m + j,min_tot));
			G[i * m + j].push_back(node ((k2 - 1) * m + j,min_tot));
			G[i * m + j].push_back(node (i * m + k3 + 1,min_tot));
			G[i * m + j].push_back(node(i * m + k4 - 1,min_tot));
		}
	}
	spfa();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章