[CF912D]Fishes - 求数学期望,乱搞

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output

While Grisha was celebrating New Year with Ded Moroz, Misha gifted Sasha a small rectangular pond of size n × m, divided into cells of size 1 × 1, inhabited by tiny evil fishes (no more than one fish per cell, otherwise they'll strife!).

The gift bundle also includes a square scoop of size r × r, designed for fishing. If the lower-left corner of the scoop-net is located at cell (x, y), all fishes inside the square (x, y)...(x + r - 1, y + r - 1) get caught. Note that the scoop-net should lie completely inside the pond when used.

Unfortunately, Sasha is not that skilled in fishing and hence throws the scoop randomly. In order to not frustrate Sasha, Misha decided to release k fishes into the empty pond in such a way that the expected value of the number of caught fishes is as high as possible. Help Misha! In other words, put k fishes in the pond into distinct cells in such a way that when the scoop-net is placed into a random position among (n - r + 1)·(m - r + 1) possible positions, the average number of caught fishes is as high as possible.

Input

The only line contains four integers n, m, r, k (1 ≤ n, m ≤ 105, 1 ≤ r ≤ min(n, m), 1 ≤ k ≤ min(n·m, 105)).

Output

Print a single number — the maximum possible expected number of caught fishes.

You answer is considered correct, is its absolute or relative error does not exceed 10 - 9. Namely, let your answer be a, and the jury's answer be b. Your answer is considered correct, if .

Examples
input
3 3 2 3
output
2.0000000000
input
12 17 9 40
output
32.8333333333
Note

In the first example you can put the fishes in cells (2, 1), (2, 2), (2, 3). In this case, for any of four possible positions of the scoop-net (highlighted with light green), the number of fishes inside is equal to two, and so is the expected value.

题目大意

给一个n*m的网格,让你在里面放k条鱼,用r*r的网覆盖(共(n - r + 1)·(m - r + 1)种方法),求覆盖到鱼的数量的期望值,(保留10位小数?)


题解

放k条鱼,不如考虑每个格子放一条鱼带来的效益

写了个暴力程序,跑出每个格子的效益:

 1 daklqw@daklqw:~/workspace/code$ ./test233
 2 12 17 9
 3 1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1
 4 2 4 6 8 10 12 14 16 18 16 14 12 10 8 6 4 2
 5 3 6 9 12 15 18 21 24 27 24 21 18 15 12 9 6 3
 6 4 8 12 16 20 24 28 32 36 32 28 24 20 16 12 8 4
 7 4 8 12 16 20 24 28 32 36 32 28 24 20 16 12 8 4
 8 4 8 12 16 20 24 28 32 36 32 28 24 20 16 12 8 4
 9 4 8 12 16 20 24 28 32 36 32 28 24 20 16 12 8 4
10 4 8 12 16 20 24 28 32 36 32 28 24 20 16 12 8 4
11 4 8 12 16 20 24 28 32 36 32 28 24 20 16 12 8 4
12 3 6 9 12 15 18 21 24 27 24 21 18 15 12 9 6 3
13 2 4 6 8 10 12 14 16 18 16 14 12 10 8 6 4 2
14 1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1
15 daklqw@daklqw:~/workspace/code$ ./test233
16 3 3 2
17 1 2 1
18 2 4 2
19 1 2 1

 

可以很方便地发现,从中间到周围,效益是不断减少的

所以我们从中间开始贪心这k条鱼,而由于这个性质,我们可以使用BFS+优先队列,每次选出一个效益最大的往四边扩展

注意到k不大,而n*m非常大,如果开二维数组会MLE,所以考虑使用set

下面献上代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <queue>
 5 #include <set>
 6 using namespace std;
 7 int n,m,r,k;
 8 const int ways[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
 9 double ans,tot;
10 struct element{
11     int x,y;long long val;
12     inline bool operator<(const element & b)const{
13         return val<b.val;
14     }
15 };
16 inline long long getv(int x,int y){
17     int t1=max(x-r+1,1),t2=max(y-r+1,1),
18         t3=min(x+r-1,n)-r+1,t4=min(y+r-1,m)-r+1;//一时想不出更好的
19     if(t3<t1|t4<t2)return -1;//防BOOM
20     return 1LL*(t3-t1+1)*(t4-t2+1);
21 }
22 priority_queue<element>q;
23 set<pair<int,int> >s;
24 int main(){
25     scanf("%d%d%d%d",&n,&m,&r,&k);
26     if(n>m)swap(n,m);//貌似没什么用
27     q.push((element){n+1>>1,m+1>>1,getv(n+1>>1,m+1>>1)});
28     s.insert(make_pair(n+1>>1,m+1>>1));
29     for(register int i=1;i<=k;++i){//找K个
30         element t=q.top();q.pop();
31         tot+=t.val;
32         for(register int j=0;j<4;++j){//BFS
33             int tx=t.x+ways[j][0],
34                 ty=t.y+ways[j][1];
35             if(tx<1||ty<1||tx>n||ty>m)continue;
36             if(s.find(make_pair(tx,ty))!=s.end())continue;
37             q.push((element){tx,ty,getv(tx,ty)});
38             s.insert(make_pair(tx,ty));
39         }
40     }
41     printf("%.10lf\n",tot/double(n-r+1)/double(m-r+1));//输出期望值
42     return 0;
43 }

 

124ms,貌似不慢,并没有时间参加这场,所以开了模拟比赛(我们这些没rating的div2蒟蒻一起打的比赛)

转载于:https://www.cnblogs.com/daklqw/p/8231284.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值