小Y的棋盘问题 题解

有一个n*m的棋盘,上面有一些棋子,每行每列最多只会有一个棋子,不会有两个棋子八连通。问随机一个空格子作为起点,再随机地选择一个空格子作为终点,求问不经过任意棋子最短路的期望长度是多少。多组,n,m<=2000。

首先答案分子显然是所有点对距离之和,分母就是不是棋子的位置个数的平方。

假装没有棋子,那么距离就是曼哈顿距离了。那么我们可以考虑将x项和y项分开统计,所以只要按x、y坐标顺序枚举点即可。

现在有了棋子,我们考虑哪些东西会受到影响。

①同一行/同一列的被棋子隔开,这样肯定距离要加2。

②那不是同一行,同一列呢?

经过一番思考,我们可以发现对于一个蓝色位置的格子,只有红色位置的格子到这个点距离要加2。

image

我来解释一下...就是说首先要是连续的一串列都有障碍,然后障碍的位置还要是单调的。

这样我们就模拟一下就行了。似乎也不是特别难写。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
#define S 1004
int T,n,m,hang[S],lie[S];
typedef long long ll;
char cs[S][S];
void sol()
{
    memset(hang,0,sizeof(hang));
    memset(lie,0,sizeof(lie));
    ll cnt=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",cs[i]+1);
        for(int j=1;j<=m;j++)
        {
            if(cs[i][j]=='G') hang[i]=j, lie[j]=i;
            else ++cnt;
        }
    }
    long long sum=0;
    //hang
    {
        long long s=0,c=0;
        for(int i=1;i<=n;i++)
        {
            long long cur=m-(bool)hang[i];
            sum+=(i*c-s)*cur;
            s+=i*cur; c+=cur;
        }
    }
    //lie
    {
        long long s=0,c=0;
        for(int j=1;j<=m;j++)
        {
            long long cur=n-(bool)lie[j];
            sum+=(j*c-s)*cur;
            s+=j*cur; c+=cur;
        }
    }
    for(int i=1;i<=n;i++)
        if(hang[i]) sum+=(hang[i]-1)*(ll)(m-hang[i])*2;
    for(int i=1;i<=m;i++)
        if(lie[i]) sum+=(lie[i]-1)*(ll)(n-lie[i])*2;
    //hang
    {
        for(int s=0;s<=1;s++)
        {
            long long ss=0;
            for(int i=1;i<=n;i++)
            {
                if(!hang[i]) {ss=0; continue;}
                if(hang[i-1]&&(hang[i]>hang[i-1])==s)
                    sum+=ss*((!s)?(hang[i]-1):(m-hang[i]));
                else
                    ss=0;
                ss+=((s)?(hang[i]-1):(m-hang[i]))*2;
            }
        }
    }
    //lie
    {
        for(int s=0;s<=1;s++)
        {
            long long ss=0;
            for(int i=1;i<=m;i++)
            {
                if(!lie[i]) {ss=0; continue;}
                if(lie[i-1]&&(lie[i]>lie[i-1])==s)
                    sum+=ss*((!s)?(lie[i]-1):(n-lie[i]));
                else
                    ss=0;
                ss+=((s)?(lie[i]-1):(n-lie[i]))*2;
            }
        }
    }
    cnt*=cnt; sum*=2;
    printf("%.4lf
",sum/(double)cnt);
}
int main()
{
    freopen("chess.in","r",stdin);
    freopen("chess.out","w",stdout);
    scanf("%d",&T);
    while(T--) sol();
}
原文地址:https://www.cnblogs.com/zzqsblog/p/5719366.html