[NOIP模拟]路径

题目描述:
这里写图片描述
样例输入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;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值