[NOIP模拟]路径

来源:互联网 发布:打骚扰电话软件 编辑:程序博客网 时间:2024/06/16 13:09

题目描述:
这里写图片描述
样例输入1:
2 2
..
.X
样例输出1:
0.888889
样例输入2:
3 3

.X.

样例输出2:
2.000000
数据规模:
对于 30% 的数据:n,m≤50;
对于 100% 的数据:2≤n,m≤10
题目分析:
1、不考虑障碍时,在矩阵里,最短距离就是行数差加列数差,可以对应到以起点、终点为顶点的矩形,路径可以移到边上,就是长宽之和。
2、考虑障碍,如果恰巧每一行都被挡住,由因为题目中性质1,所以只需绕一次,路径长度增加2。
3、所以总的只需把所有的加起来除以路径总数就能得答案。
附代码:

#include<iostream>#include<cstring>#include<string>#include<ctime>#include<queue>#include<iomanip>#include<cstdio>#include<cstdlib>#include<cmath>#include<cctype>#include<set>#include<map>#include<algorithm>using namespace std;char s[1005];int totx,n,m,liex[1005],hangx[1005];long long work(int n,int m,int a[])//以行为例 {    long long res=0;    for(int i=1;i<=n;i++)//枚举每一行,起始行     {        long long sig=0,tot=m-a[i];        for(int j=1;j<=n;j++)//枚举每一行,终点行             if(a[j])//判断有障碍,则这一行会少一个可以终点的点                 sig+=(m-1)*abs(i-j);//计算起始位置与终点位置的行差,再乘以终点的个数             else                sig+=m*abs(i-j);        if(a[i])//同理判断             res+=(m-1)*sig;//起始点的个数乘以到所有终点的路径和         else            res+=m*sig;        if(a[i])//判断是否存在连续的障碍         {            int l=i-1,r=i+1;            while(a[l]>a[l+1])//向上找,如果连续,则障碍后面的所有点都不可直接到达                 tot+=m-a[l],l--;            while(a[r]>a[r-1])//同理                 tot+=m-a[r],r++;            res+=2*2*tot*(a[i]-1);//从障碍左到障碍右不可直接到达,反过来也是,所以 *2,不可直接到达路径+2,所以整体*2         }                       // tot不可到达的总点数,a[i]-1起始点的个数     }    return res;}int main(){    //freopen("length.in","r",stdin);    //freopen("length.out","w",stdout);    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    {        scanf("%s",s);        for(int j=1;j<=m;j++)        if(s[j-1]=='X')        {            hangx[i]=j;            liex[j]=i;            totx++;        }    }    int tot=n*m-totx;//所有可以站人的点,tot*tot就是两人所有的随机站位     double ans=(work(n,m,hangx)+work(m,n,liex))*1.0/tot/tot;    printf("%0.6f\n",ans);    return 0;}
原创粉丝点击