Description
给定一个n行m列的字符矩阵,’.’代表空地,’X’代表障碍。移动的规则是:每秒钟以上下左右四个方向之一移动一格,不能进入障碍。
计算:在空地中随机选择起点和终点(可以重合,此时最短耗时为0),从起点移动到终点最短耗时的平均值。
每一行每一列至多有1个障碍,并且障碍不在对角线方向相邻。以下矩阵是不合法的:
.X
X.
2<=n,m<=1000
Analysis
对于一些特殊情况(无需绕行),答案就是各个点对坐标的绝对值之差。
可是可能会绕行,比如说:
…
.x.
(2,1)到(2,3)多走了两步。
怎么办?
由于矩阵有上述限制,我们手玩一下可以发现,要么绕行2步要么不绕行。
绕行的点对满足什么条件?
首先上述情况是一种。
III….
IIX…
II..X.
IX….
I….X
X…..
S…..
S到所有的I需要绕行,就这两种情况。自己总结吧。
唉,这结论题结论的==
Code
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int N=1010;
int n,m,num,r[N],c[N],sr[N],sc[N];
bool a[N][N];
int main()
{
char ch;
scanf("%d %d\n",&n,&m);
fo(i,1,n)
{
fo(j,1,m)
{
scanf("%c",&ch);
if(ch=='.') num++,a[i][j]=1,sr[i]++,sc[j]++;
else r[i]=j,c[j]=i;
}
scanf("\n");
}
long long ans=0;
fo(i,1,n-1)
fo(j,i+1,n) ans+=2*(j-i)*sr[i]*sr[j];
fo(i,1,m-1)
fo(j,i+1,m) ans+=2*(j-i)*sc[i]*sc[j];
fo(i,1,m)
if(c[i])
{
int x=c[i]-1,y=n-c[i],nx=i,sum=0;
ans+=x*y*4;
if(c[i+1]>c[i])
{
for(;c[nx+1]>c[nx];sum+=m-c[++nx]);
ans+=x*sum*4;
}
else
{
for(;c[nx+1] && c[nx+1]<c[nx];sum+=c[++nx]-1);
ans+=y*sum*4;
}
}
fo(i,1,n)
if(r[i])
{
int x=r[i]-1,y=m-r[i],nx=i,sum=0;
ans+=x*y*4;
if(r[i+1]>r[i])
{
for(;r[nx+1]>r[nx];sum+=n-r[++nx]);
ans+=x*sum*4;
}
else
{
for(;r[nx+1] && r[nx+1]<r[nx];sum+=r[++nx]-1);
ans+=y*sum*4;
}
}
printf("%.4lf",ans*1.0/num/num);
return 0;
}