这题网上大多讲得很清楚就不说了。。。
http://blog.csdn.net/y1196645376/article/details/52187900//这个老哥讲得好
主要就是注意一下(long long)就好了,还有就是计数的关键是注意到我们可以把曼哈顿距离分拆成横和竖两个方向分别计算。
第一行的曼哈顿距离的贡献就是第二行,第三行,第四行,。。。哪些行的点到第一行的竖直距离是1 2 3 . 。 。 。
第一列的曼哈顿距离贡献是第二列,第三列,第四列,。。。。。哪些列的点到第一列的横向距离是1 2 3 . 。 。 。 。
对于一个点也进行分拆:
如一个点(i,j)
先计算竖向方向的距离和,有i个竖,所以是i*(j-1)*j/2;
横是i*(i-1)*j/2;
这样计算会带来一些问题;
就是一个G点会重复计算你用这个栗子调试下就明白了:
3 4
G###
##G#
####
2.2600
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
char mapp[1010][1010];
typedef long long ll;
struct pairr
{
int i, j;
ll linei, hengj;
};
pairr p[1500];
int n, m,t,tott;
ll sum = 0;
ll amount = 0;
bool com(pairr a, pairr b)
{
return a.i < b.i;
}
bool com2(pairr a, pairr b)
{
return a.j < b.j;
}
ll get(ll i, ll j)
{
return j*((i*(i - 1)) / 2)+i*((j*(j-1))/2);
}
int main()
{
scanf("%d", &t);
while (t--)
{
tott = 0; sum = 0; amount = 0;
scanf("%d%d", &n, &m);
sum = (1ll*(m*n - 1)*(m + n)*m*n)/3;
amount = 1ll*m*n*(m*n);
getchar();
for (int i = 1; i <= n; i++)
{
gets(mapp[i]+1);
for (int j = 1; j <= m; j++)
{
if (mapp[i][j] == 'G')
{
p[tott].i = i; p[tott++].j = j;
amount -= (m*n - 1-(tott-1)) * 2;
amount--;
sum -= (get(i, j) + get(n - i + 1, j) + get(i, m - j + 1) + get(n - i + 1, m - j + 1)) * 2;
sum += (get(1, j) + get(i, 1) + get(1, m - j + 1) + get(n - i + 1, 1))*2;
}
}
}
for (int i = 0; i < tott; i++)
{
for (int j = 0; j < i; j++)
{
int p1 = abs(p[i].i - p[j].i); int p2 = abs(p[i].j - p[j].j);
sum += (p1 + p2) * 2;
}
}
sort(p, p + tott, com2);
ll tempsum = 0;
for (int i = 0; i < tott; i++)
{
tempsum += (n - p[i].i);
p[i].linei = tempsum;
if (p[i].j + 1 != p[i + 1].j || p[i].i < p[i + 1].i)
tempsum = 0;
}
for (int i = 0; i < tott; i++)
{
if (p[i].linei)
sum += (p[i].linei*(p[i].i - 1)) *4,
p[i].linei = 0;
}
tempsum = 0;
for (int i = tott - 1; i >= 0; i--)
{
if (tempsum)
p[i].linei = tempsum;
if (p[i].j - 1 != p[i - 1].j || p[i].i < p[i - 1].i)
tempsum = 0;
else
tempsum += (n - p[i].i);
}
for (int i = 0; i < tott; i++)
{
if (p[i].linei)
sum += (p[i].linei*(p[i].i - 1)) * 4,
p[i].linei = 0;
}
tempsum = 0;
sort(p, p + tott, com);
for (int i = 0; i < tott; i++)
{
tempsum += (m - p[i].j);
p[i].hengj = tempsum;
if (p[i].i+1!= p[i + 1].i || p[i].j < p[i + 1].j)
tempsum = 0;
}
for (int i = 0; i < tott; i++)
{
if (p[i].hengj)
{
sum += (p[i].j - 1)*(p[i].hengj) *4,
p[i].hengj=0;
}
}
tempsum = 0;
for (int i = tott - 1; i >= 0; i--)
{
if (tempsum)
p[i].hengj = tempsum;
if (p[i].i - 1 != p[i - 1].i || p[i].j < p[i - 1].j)
tempsum = 0;
else
tempsum += (m - p[i].j);
}
for (int i = 0; i < tott; i++)
{
if (p[i].hengj)
{
sum += (p[i].j - 1)*(p[i].hengj) * 4,
p[i].hengj = 0;
}
}
double rate = (sum*1.0) / (amount*1.0);
printf("%.4llf\n", rate);
}
}