题意简述:往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 ",x,y) #define pf(x) printf("%d ",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 ",1.0); } else { printf("%.10f ",calc()); } }