[第一场(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
");
	else 	
		printf("%d",dis[e]);
}
int main(){
	scanf ("%d%d",&n,&m);
	for (int i = 1;i <= n;i ++){
		scanf("
");
		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();
}
原文地址:https://www.cnblogs.com/lover-fucker/p/13566660.html