旅行

本文介绍了一种计算旅行矩阵中从随机起点到随机终点最短耗时平均值的方法。利用曼哈顿距离和障碍物处理技巧,文章提供了一个高效的算法实现方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

旅行

【问题描述】
给定一个n 行m 列的字符矩阵,‘.’表示空地,‘X’表示障碍。移动的规则是:每秒钟可以上下
左右四个方向之一移动一格,不能进入障碍。计算:在空地中随机选择起点和终点(可以重合,此时
最短耗时为0),从起点移动到终点最短耗时的平均值。
每一行每一列至多有1 个障碍,并且障碍不在对角线方向相邻。以下矩阵是不合法的:
.X
X.
【输入】
每一行两个整数n,m。
接下来n 行,每行m 个字符‘.’或‘X’。在50%的数据中,保证每个字符都是‘.’。
【输出】
输出平均耗时,四舍五入保留4位小数。数据保证在[ans-10^7,ans+10^7]范围之内输出一致,
ans 是标准答案。
【输入样例】
2 2
..
.X
【输出样例】
0.8889
【Hint】
若有p 个空地,则随机选择起点到终点最短耗时的平均值为任意两点间曼哈顿距离之和除以空地
总数的平方:

这道题乍一眼看我是觉得很烦的,前一天我刚刚看了期望啊概率啊什么的然后第一眼看就以为要算期望什么 后来发现这道题 根本没这么麻烦

然后在考虑有过X的时候要怎么处理——>发现题目里说了“每一行每一列至多有1 个障碍,并且障碍不在对角线方向相邻。”
啊真的好简单啊
就是说如果起点和终点只要不在同一条直线或者同一条竖线上,就是简简单单求两点之间的曼哈顿距离:
(x1,y1) (x2,y2) 之间的曼哈顿距离是|x1-x2|+|y1-y2|
则任意两行之间的距离就是 (i行空地个数)(j行空地个数)(i-j)
如果在同一行或者同一列
则路途中遇到一个X就把步数加2

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define ll long long
const int N=1010;
const int INF=200000000;
using namespace std;
int a[N][N];
double ans=0,row[N],line[N],line1[N],row1[N],tot,n,m;
int main()
{
    freopen("journey.in","r",stdin);
    freopen("journey.out","w",stdout);
    cin>>n>>m;
    for (ll i=1; i<=n; i++)
      line[i]=INF;
    for (ll i=1; i<=m; i++)
      row[i]=INF;
    for (ll i=1; i<=n; i++) 
    {
        for (ll j=1; j<=m; j++)
        {
            char c;
            cin>>c;
            if(c=='X') line[i]=j,row[j]=i,a[i][j]=1;
            else a[i][j]=1,tot++,line1[i]++,row1[j]++;
        }
    }
    for(ll i=1; i<=n; i++) 
      for (ll j=i; j<=n; j++) 
        ans+=(line1[i]*line1[j]*(j-i)*2.0)/tot/tot;
    for(ll i=1; i<=m; i++) 
      for (ll j=i; j<=m; j++)
        ans+=(row1[i]*row1[j]*(j-i)*2.0)/tot/tot;
    for (ll i=1; i<=m; i++) 
    if(row[i]<INF)
    {
        double y=row[i]-1; 
        for(int j=i;j>1&&row[j-1]<row[j];j--) 
          y+=row[j-1]-1;
        for(int j=i;j<m&&row[j+1]<row[j];j++) 
          y+=row[j+1]-1;
        ans+=4.0*(n-row[i])*y/tot/tot;
    }
    for (ll i=1; i<=n; i++)
    if(line[i]<INF)
    {
        double y=line[i]-1; 
        for(int j=i;j>1&&line[j-1]<line[j];j--) 
           y+=line[j-1]-1;
        for(int j=i;j<n&&line[j+1]<line[j];j++) 
          y+=line[j+1]-1;
        ans+=4.0*(m-line[i])*y/tot/tot;
    }
    printf("%.4lf\n",ans);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值