icodelab 最短路

描述

在一个n行m列的矩阵中,’P’代表平缓的场地,’H’代表小山。人的起点是在某个P的空格中,在这个矩阵中移动的规则如下:

每秒钟人可以向上下左右四个方向中任何一个方向移动一格,但需要注意的是不能进入小山所在的格子。

现在在P中随机选择起点和终点(起点和终点是可以重合的,如果重合则耗时为0),请你计算从起点移动到终点的最短耗时的平均值。

给你的矩阵有一个特点,每一行每一列至多有1个H格,并且H格不在对角线方向相邻。即给你数据中不会存在以下矩阵格式的矩阵:

PH

HP

输入

输入数据格式:

第一行两个整数n, m。

接下来n行,每行m个字符’P’或’H’。

输出

输出平均耗时值,请保留4位小数,需要四舍五入。

输入样例 1

2 2 
PH
PP

输出样例 1

0.8889

输入样例 2

3 3
PPP
HPP
PPP

输出样例 2

1.8438

提示

2<=n,m<=1000

思路(详见代码)代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=1010;
const int oo=1e9;

int n,m;
double ans,p;
char a[N][N];
double b[N],c[N],d[N],e[N];

int main () {
	//freopen("zdl.in","r",stdin);
	//freopen("zdl.out","w",stdout);
	scanf("%d%d\n",&n,&m);//一定要加\n!!!
	for (int i=1; i<=n; i++)
		d[i]=2147483647;
	for (int i=1; i<=m; i++)
		e[i]=2147483647;//memset只能赋0
	for(int i=1; i<=n; i++) {//n行
		for(int j=1; j<=m; j++) {//m列 
			scanf("%c",&a[i][j]);//输入每个字符
			if(a[i][j]=='P') {
				p++;//统计有多少个空地 
                                b[i]++;//统计第i行有多少块空地 
                                c[j]++;//统计第j列有多少块空地 
			} else {
				d[i]=j;//记录障碍所在的位置 
			        e[j]=i;
			}
		}
		scanf("\n");//一定要加\n!!!
	}
        //先计算任意两点间的曼哈顿距离,这个距离分成两部分计算,
	//下面这个是先计算任意两行中两个点之间的y2-y1的距离 
	for(int i=1; i<=n; i++)
		for(int j=1; j<=n; j++)
			ans+=b[i]*b[j]*abs(i-j);
        //下面这个是先计算任意两列中两个点之间的x2-x1的距离 
	for(int i=1; i<=m; i++)
		for(int j=1; j<=m; j++)
			ans+=c[i]*c[j]*abs(i-j);
	for(int i=1; i<=m; i++)
		if(e[i]<2147483647) {//说明该列上有障碍  e[i]里保存的是该列上的障碍是在哪一行 
			int t=e[i]-1,k=i;//t是障碍所在行的上一行
			while(k>1&&e[k-1]<e[k]) {//不是第一列,且左边那一列的障碍比当前列的障碍高 
				k--;//向左边列查找 
                                t+=e[k]-1;//这一列上面有t个点,这些点到障碍所在位置的下面的所有的点距离都要加2 
			}
			k=i;
			while(k<m&&e[k+1]<e[k]) {//不是最后一列,且右边那一列的障碍比当前列的障碍高 
				k++;//向右边列查找 
				t+=e[k]-1;
			}
			ans+=(n-e[i])*t*4;//n-e[i]表示障碍下面有多少个点 
		}
	for(int i=1; i<=n; i++)
		if(d[i]<2147483647) {
			int t=d[i]-1,k=i;
			while(k>1&&d[k-1]<d[k]) {
				k--;
				t+=d[k]-1;
			}
			k=i;
			while(k<n&&d[k+1]<d[k]) {
				k++;
				t+=d[k]-1;
			}
			ans+=(m-d[i])*t*4;
		}
	printf("%.4lf",ans/p/p);
	return 0;
}
            

 

 

猜你喜欢

转载自www.cnblogs.com/mysh/p/11306524.html