cf912D

题意简述:往n*m的网格中放k条鱼,一个网格最多放一条鱼,然后用一个r*r的网随机去捞鱼,问怎么怎么放鱼能使得捞鱼的期望最大,输出这个期望

题解:肯定优先往中间放,这里k不大,因此有别的简单方法,否则推公式各种情况烦死人,我们对于每一行来说将中间的数加进去,然后用set来维护k次就好了

#include<bits/stdc++.h>
#define forn(i, n) for (int i = 0 ; i < int(n) ; i++)
#define fore(i, s, t) for (int i = s ; i < (int)t ; i++)
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define pf2(x,y) printf("%d %d\n",x,y)
#define pf(x) printf("%d\n",x)
#define each(x) for(auto it:x)  cout<<it<<endl;
#define pii pair<int,int>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
const int maxm=2e5+5;
const int inf=1e9;
int n,m,r,k;
struct cell{
	int x,y,d;
	ll val;
	cell(int x,int y,int d):x(x),y(y),d(d){
		val=(min(m+1,y+r)-max(y,r))*1ll*(min(n+1,x+r)-max(x,r));
	}
	bool operator<(const cell& rhs)const {
		return val>rhs.val;
	}
};
multiset<cell> ms;
double calc(){
	for (int i = 1; i <= n; i++) {
		int j = m / 2;
		ms.insert({ i, j, 0 });
		ms.insert({ i, j + 1, 1 });
	}
	ll total = 0;
	for(int i=0;i<k;i++){
		auto it = *ms.begin();
		total += it.val;
		ms.erase(ms.begin());
		if (it.d == 1 && it.y < m)
			ms.insert({ it.x, it.y + 1, 1 });
		else if (it.d == 0 && it.y > 1)
			ms.insert({ it.x, it.y - 1, 0 });
	}
	return (double)total / ((n - r + 1) * 1LL * (m - r + 1));
}
int main(){
	cin>>n>>m>>r>>k;
	if(n>m) swap(n,m);
	if(m==1) {
		printf("%.10f\n",1.0);
	} 
	else {
		printf("%.10f\n",calc());
	}
}

  

posted on 2020-02-22 22:29  欣崽  阅读(225)  评论(0编辑  收藏  举报

导航