这是个数学题a…
所有的
r∗r
r
∗
r
的scoop的数目为
(n−r+1)∗(m−r+1)
(
n
−
r
+
1
)
∗
(
m
−
r
+
1
)
其中包含坐标
(x,y)
(
x
,
y
)
的scoop的数目为(坐标index从1开始)
f(x,y)=(min(n+1,x+r)−max(x,r))∗(min(m+1,y+r)−max(y,r))
f
(
x
,
y
)
=
(
m
i
n
(
n
+
1
,
x
+
r
)
−
m
a
x
(
x
,
r
)
)
∗
(
m
i
n
(
m
+
1
,
y
+
r
)
−
m
a
x
(
y
,
r
)
)
f(x0,y)
f
(
x
0
,
y
)
在固定x坐标的情况下,
f(x0,y)
f
(
x
0
,
y
)
先增后减,最大值点为
⌊m+12⌋
⌊
m
+
1
2
⌋
全局最大值点为
(⌊n+12⌋,⌊m+12⌋)
(
⌊
n
+
1
2
⌋
,
⌊
m
+
1
2
⌋
)
因此,可以得到的算法为:1.从每一行的最大值点开始,向两边扩展;2.从全局最大值点开始BFS
题目说精确度1e-9,小数要输出到第9位以后,默认double输出6位导致WA
代码实现算法1,其中’D’表示decrease,向左边扩展,‘I’表示increase,向右边扩展
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m, r, k;
struct Point {
int x, y;
ll val;
char type;
Point(int x, int y, char type)
: x(x), y(y), type(type) {
val = (min(n + 1, x + r) - max(x, r)) * 1LL * (min(m + 1, y + r) - max(y, r));
}
bool operator<(const Point& p) const {
return val < p.val;
}
};
void solve() {
priority_queue<Point, vector<Point> > que;
for (int x = 1; x <= n; x++) {
int mid = (m + 1) / 2;
que.push(Point(x, mid, 'D'));
if (mid + 1 <= m) {
que.push(Point(x, mid + 1, 'I'));
}
}
ll sum = 0;
while (k--) {
Point p = que.top(); que.pop();
sum += p.val;
if (p.type == 'D' && p.y - 1 >= 1) {
que.push(Point(p.x, p.y - 1, 'D'));
}
if (p.type == 'I' && p.y + 1 <= m) {
que.push(Point(p.x, p.y + 1, 'I'));
}
}
printf("%.9lf\n", (double)sum / (n - r + 1) / (m - r + 1));
}
int main() {
scanf("%d %d %d %d", &n, &m, &r, &k);
solve();
return 0;
}