zoukankan      html  css  js  c++  java
  • [CF912D]Fishes

    给一个 (n imes m) 的网格,让你在里面放刚好 (k) 条鱼(位置不能相同),随机用一个 (r imes r) 的网覆盖(共 ((n - r + 1)(m - r + 1)) 种方法),最大化覆盖到鱼的数量的期望。


    由期望的线性性,答案是每个格子被访问到的期望。我们不妨先将答案乘上 ((n - r + 1)(m - r + 1)) 来考虑。

    我们想象有一个滑动的窗口,它只在 (x) 轴滑和只在 (y) 轴滑的过程——实际上两维是独立的。

    对于一维,记长度为 (n),考虑左端点可行位置,得到一个数组 (A_i = min(i, n - r + 1) - max(1, i - r + 1) + 1)

    那么,在每个位置的贡献就是 (x) 轴数组 (A)(y) 轴数组 (B) 的笛卡尔积 (M_{i,j} = A_i B_j)

    (A)(B) 显然是单峰的(当然也是对称的),所以笛卡尔积之后也是单峰的。

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

    所以我们直接从最中间开始贪心,用 BFS 和 优先队列找到前 k 大的位置即可。

    下面是远古时期的代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <set>
    using namespace std;
    int n,m,r,k;
    const int ways[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
    double ans,tot;
    struct element{
    	int x,y;long long val;
    	inline bool operator<(const element & b)const{
    		return val<b.val;
    	}
    };
    inline long long getv(int x,int y){
    	int t1=max(x-r+1,1),t2=max(y-r+1,1),
    		t3=min(x+r-1,n)-r+1,t4=min(y+r-1,m)-r+1;
    	if(t3<t1|t4<t2)return -1;
    	return 1LL*(t3-t1+1)*(t4-t2+1);
    }
    priority_queue<element>q;
    set<pair<int,int> >s;
    int main(){
    	scanf("%d%d%d%d",&n,&m,&r,&k);
    	if(n>m)swap(n,m);
    	q.push((element){n+1>>1,m+1>>1,getv(n+1>>1,m+1>>1)});
    	s.insert(make_pair(n+1>>1,m+1>>1));
    	for(int i=1;i<=k;++i){
    		element t=q.top();q.pop();
    		tot+=t.val;
    		for(register int j=0;j<4;++j){
    			int tx=t.x+ways[j][0],
    			ty=t.y+ways[j][1];
    			if(tx<1||ty<1||tx>n||ty>m)continue;
    			if(s.find(make_pair(tx,ty))!=s.end())continue;
    			q.push((element){tx,ty,getv(tx,ty)});
    			s.insert(make_pair(tx,ty));
    		}
    	}
    	printf("%.10lf
    ",tot/double(n-r+1)/double(m-r+1));
    	return 0;
    }
    
  • 相关阅读:
    进程池的回调函数
    进程通信(multiprocessing.Queue)
    自动化批量管理工具salt-ssh
    自动化批量管理工具pssh
    Saltstack自动化操作记录(2)-配置使用
    Saltstack自动化操作记录(1)-环境部署
    RocketMQ 简单梳理 及 集群部署笔记
    CentOS7下单机部署RabbltMQ环境的操作记录
    centos6下ActiveMQ+Zookeeper消息中间件集群部署记录
    [Centos6.9下RabbitMQ集群部署记录]
  • 原文地址:https://www.cnblogs.com/daklqw/p/8231284.html
Copyright © 2011-2022 走看看