旅行
题目大意
给定一个
n
行
计算:在空地中随机选择起点和终点(可以重合,此时最短耗时为
0
),从起点移动到终点最短耗时的平均值。
每一行每一列至多有
数据范围
2
<=
题解
首先,这题的解法比较玄学。
首先,一对点对对应着一条路径。
暂且假设所有路径的的时间总和为所有点对的曼哈顿距离。
先求出曼哈顿距离和,再加上少了的那一部分。
那少了的那一部分怎么算呢?
我们看到障碍这个神奇的条件。
这意味着什么呢?
这意味着一个点对的路径长度要么为它们的曼哈顿距离,要么为曼哈顿距离+2。(这很显然,请读者自行思考)
这下问题就简单多了,我们只需路径长度为曼哈顿距离+2的点对数就可以知道答案了。
可是我们应该怎么求满足条件的点对数呢?
看到下图,由红色的点走到蓝色的点的路径长度为曼哈顿距离+2(需要绕行,X表示障碍),我们找一下这些点对有什么共性。
从直观上来看,一个
X
下方的点到这个
根据以上规律,统计出需要+
2
<script type="math/tex" id="MathJax-Element-29">2</script>的点对数加入答案即可。
Code(Pascal)
var
n,m,j,k,l,i,p:longint;
ans,kk,o:int64;
ch:array[0..2000,0..2000] of char;
hq,lq,hh,ll:array[-1..2000] of int64;
begin
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
read(ch[i,j]);
readln;
end;
for i:=1 to n do
begin
for j:=1 to m do
if ch[i,j]='.' then inc(hq[i]);
hq[i]:=hq[i-1]+hq[i];
kk:=kk+hq[i-1];
ans:=ans+kk*(hq[i]-hq[i-1]);
end;
for i:=1 to n do
hh[i]:=maxlongint;
for i:=1 to m do
ll[i]:=maxlongint;
for i:=1 to n do
for j:=1 to m do
if ch[i,j]='X' then
begin
hh[i]:=j;
ll[j]:=i;
end;
kk:=0;
for j:=1 to m do
begin
for i:=1 to n do
if ch[i,j]='.' then inc(lq[j]);
lq[j]:=lq[j-1]+lq[j];
kk:=kk+lq[j-1];
ans:=ans+kk*(lq[j]-lq[j-1]);
end;
for j:=1 to m do
if ll[j]<>maxlongint then
begin
p:=n-ll[j];
o:=ll[j]-1;
k:=j;
while (k<m) and (ll[k+1]<ll[k]) do
begin
inc(k);
o:=o+ll[k]-1;
end;
k:=j;
while (k>1) and (ll[k-1]<ll[k]) do
begin
dec(k);
o:=o+ll[k]-1;
end;
ans:=ans+p*o*2;
end;
for i:=1 to n do
if hh[i]<>maxlongint then
begin
p:=m-hh[i];
o:=hh[i]-1;
k:=i;
while (k<n) and (hh[k+1]<hh[k]) do
begin
inc(k);
o:=o+hh[k]-1;
end;
k:=i;
while (k>1) and (hh[k-1]<hh[k]) do
begin
dec(k);
o:=o+hh[k]-1;
end;
ans:=ans+o*p*2;
end;
o:=n*m;
ans:=ans*2;
for i:=1 to n do
for l:=1 to m do
if ch[i,l]='X' then dec(o);
o:=o*o;
writeln((ans/o):0:4);
end.