HDU 5725 Game

http://acm.split.hdu.edu.cn/showproblem.php?pid=5725
可以知道一般情况下两点之间的距离是曼哈顿距离,当且仅当两点间每排都阶梯状的阻碍,是曼哈顿距离加2。
先算总和,每个点到另一个点分为两种,横向与纵向,横向算一次,纵向算一次。
在判断有多少点有横向阻挡或纵向阻挡。

#include<iostream>
#include <cstring>
#include  <cstdio>
using namespace std;
const int Max=1005;
int x[Max],y[Max],blockx[Max],blocky[Max];
long long ans;
char a[Max][Max];
void calc(const int &n,int x[]){
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            ans+=(long long)(j-i)*x[i]*x[j];
        }
    }
}
int main(){
    int T,m,n;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        getchar();
        memset(x,0,sizeof(x));
        memset(y,0,sizeof(y));
        memset(blockx,0,sizeof(blockx));
        memset(blocky,0,sizeof(blocky));
        for (int i = 1; i <= n; i++)
            scanf("%s", a[i] + 1);
        long long cnt = 0;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                if (a[i][j] == '#')
                    x[i]++, y[j]++, cnt++;
                else
                    blockx[i] = j, blocky[j] = i;
        cnt*=cnt;
        ans=0;
        calc(n,x);
        calc(m,y);
        ans*=2;
        int sum=0;
        int tmp;
        for(int i=1;i<=n;i++){
            if(blockx[i-1]<blockx[i]){
                sum+=blockx[i]-1;
            }else if(!blockx[i]){
                sum=0;
            }else{
                sum=blockx[i]-1;
            }
            tmp=m;
            tmp-=blockx[i];
            ans+=4*tmp*sum;
        }
        sum=0;
        for(int i=n;i>=1;i--){
            tmp=m;
            if(blockx[i+1]<blockx[i]){
                tmp-=blockx[i];
            }
            else{
                tmp=0;
            }
            ans+=4*tmp*sum;
            if(blockx[i+1]<blockx[i]){
                sum+=blockx[i]-1;
            }
            else if(!blockx[i]){
                sum=0;
            }else{
                sum=blockx[i]-1;
            }
        }
        sum=0;
        for(int i=1;i<=m;i++){
            if(blocky[i-1]<blocky[i]){
                sum+=blocky[i]-1;
            }else if(!blocky[i]){
                sum=0;
            }else{
                sum=blocky[i]-1;
            }
            tmp=n;
            tmp-=blocky[i];
            ans+=4*tmp*sum;
        }
        sum=0;
        for(int i=m;i>=1;i--){
            tmp=n;
            if(blocky[i+1]<blocky[i]){
                tmp-=blocky[i];
            }
            else{
                tmp=0;
            }
            ans+=4*tmp*sum;
            if(blocky[i+1]<blocky[i]){
                sum+=blocky[i]-1;
            }
            else if(!blocky[i]){
                sum=0;
            }else{
                sum=blocky[i]-1;
            }
        }
        printf("%.4f\n",(double)ans/(double)cnt);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lxworld123/article/details/52525840