歌名 - 歌手
0:00

    【NOIP2012模拟10.25】旅行

    题目

    给定一个n行m列的字符矩阵,’.’代表空地,’X’代表障碍。移动的规则是:每秒钟以上下左右四个方向之一移动一格,不能进入障碍。
    计算:在空地中随机选择起点和终点(可以重合,此时最短耗时为0),从起点移动到终点最短耗时的平均值。
    每一行每一列至多有1个障碍,并且障碍不在对角线方向相邻。以下矩阵是不合法的:
    .X

    X.

    分析

    50%的数据,全都是空地,答案就是所有两点间的曼哈顿距离和。
    很容易求,\({第i行空地的数量}*{第j行空地的数量}*|i-j|*2\)
    因为每一行每一列至多有1个障碍,并且障碍不在对角线方向相邻。得出从A走到B的耗时,要么等于AB的曼哈顿距离,要么等于AB的曼哈顿距离+2。
    现在考虑什么情况下距离加二。
    观察下图,规律显而易见,我就不多说了,
    这里写图片描述

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const int maxlongint=2147483647;
    const int mo=1000000007;
    const int N=1005;
    using namespace std;
    int a[N][N],n,m,sum,sx[N],sy[N],xx[N],xy[N];
    double ans;
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    		{
    			char c=getchar();
    			while(c!='.' && c!='X') c=getchar();
    			if(c=='.')
    			{
    				sx[i]++;
    				sy[j]++;
    				sum++;
    			}
    			else
    			{
    				xx[i]=j;
    				xy[j]=i;	
    			}
    		}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			ans+=abs(i-j)*sx[i]*sx[j]*1.0/sum/sum;
    	for(int i=1;i<=m;i++)
    		for(int j=1;j<=m;j++)
    			ans+=abs(i-j)*sy[i]*sy[j]*1.0/sum/sum;
    	for(int i=1;i<=n;i++)
    	if(xx[i])
    	{
    		int mn=maxlongint,mx=-1;
    		for(int j=i;j>=1;j--)
    		{
    			if(xx[j]>mx && xx[j])
    			{
    				ans+=1.0*(xx[i]-1)*(m-xx[j])*2/sum/sum;
    				mx=xx[j];
    			}
    			else
    			break;
    		}
    		for(int j=i;j>=1;j--)
    		{
    			if(xx[j]<mn && xx[j])
    			{
    				ans+=1.0*(xx[j]-1)*(m-xx[i])*2/sum/sum;
    				mn=xx[j];
    			}
    			else
    			break;
    		}
    		mn=xx[i],mx=xx[i];
    		for(int j=i+1;j<=n;j++)
    		{
    			if(xx[j]>mx && xx[j])
    			{
    				ans+=1.0*(xx[i]-1)*(m-xx[j])*2/sum/sum;
    				mx=xx[j];
    			}
    			else
    			break;
    		}
    		for(int j=i+1;j<=n;j++)
    		{
    			if(xx[j]<mn && xx[j])
    			{
    				ans+=1.0*(xx[j]-1)*(m-xx[i])*2/sum/sum;
    				mn=xx[j];
    			}
    			else
    			break;
    		}
    	}
    	for(int i=1;i<=m;i++)
    	if(xy[i])
    	{
    		int mn=maxlongint,mx=-1;
    		for(int j=i;j>=1;j--)
    		{
    			if(xy[j]>mx && xy[j])
    			{
    				ans+=1.0*(xy[i]-1)*(n-xy[j])*2/sum/sum;
    				mx=xy[j];
    			}
    			else
    			break;
    		}
    		for(int j=i;j>=1;j--)
    		{
    			if(xy[j]<mn && xy[j])
    			{
    				ans+=1.0*(xy[j]-1)*(n-xy[i])*2/sum/sum;
    				mn=xy[j];
    			}
    			else
    			break;
    		}
    		mn=xy[i],mx=xy[i];
    		for(int j=i+1;j<=m;j++)
    		{
    			if(xy[j]>mx && xy[j])
    			{
    				ans+=1.0*(xy[i]-1)*(n-xy[j])*2/sum/sum;
    				mx=xy[j];
    			}
    			else
    			break;
    		}
    		for(int j=i+1;j<=m;j++)
    		{
    			if(xy[j]<mn && xy[j])
    			{
    				ans+=1.0*(xy[j]-1)*(n-xy[i])*2/sum/sum;
    				mn=xy[j];
    			}
    			else
    			break;
    		}
    	}
    	printf("%.4lf",ans);
    }
    
    posted @ 2018-05-16 12:20  无尽的蓝黄  阅读(275)  评论(0编辑  收藏  举报