CF739E Gosha is hunting(费用流,期望)

根据期望的线性性答案就是捕捉每一只精灵的概率之和。
捕捉一只精灵的方案如下:
1.使用一个\(A\)精灵球,贡献为\(A[i]\)
2.使用一个\(B\)精灵球,贡献为\(B[i]\)
3.使用一个\(A\)精灵球和一个\(B\)精灵球,贡献为\(A[i]+B[i]-A[i]*B[i]\)
然后我们可以这样建图:
源点\(S\)向两个精灵球连容量为精灵球数量,费用为\(0\)的边。
\(A\)精灵球向i连容量为\(1\),费用为\(A[i]\)的边。
\(B\)精灵球向i连容量为\(1\),费用为\(B[i]\)的边。
然后每一只精灵向T连一条容量为\(1\),费用为\(0\)的边和一条容量为\(1\),费用为\(-A[i]*B[i]\)的边。
然后跑最大费用流即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
const int N=2200;
const double INF=1e9;
const double eps=1e-8;
int n,a,b,S,T;
double A[N],B[N],ans,dis[N];
bool vis[N];
int cnt=1,head[N],from[N];
struct edge{
    int to,nxt,flow;
    double cost;
}e[N*8];
void add_edge(int u,int v,int flow,double cost){
    cnt++;
    e[cnt].nxt=head[u];
    e[cnt].to=v;
    e[cnt].flow=flow;
    e[cnt].cost=cost;
    head[u]=cnt;
}
bool spfa(){
    for(int i=S;i<=T;i++)dis[i]=INF;
    dis[S]=0;
    queue<int> q;
    q.push(S);
    vis[S]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(dis[v]>dis[u]+e[i].cost+eps&&e[i].flow){
                dis[v]=dis[u]+e[i].cost;
                from[v]=i;
                if(vis[v]==0)vis[v]=1,q.push(v);
            }
        }
    }
    if(dis[T]==INF)return false;
    int mn=INF;
    for(int i=T;i!=S;i=e[from[i]^1].to)
        mn=min(mn,e[from[i]].flow);
    ans+=dis[T]*mn;
    for(int i=T;i!=S;i=e[from[i]^1].to){
        e[from[i]].flow-=mn;
        e[from[i]^1].flow+=mn;
    }
    return true;
}
int main(){
    scanf("%d%d%d",&n,&a,&b);
    for(int i=1;i<=n;i++)scanf("%lf",&A[i]);
    for(int i=1;i<=n;i++)scanf("%lf",&B[i]);
    S=0;T=2+n+1;
    add_edge(S,1,a,0);add_edge(1,S,0,0);
    add_edge(S,2,b,0);add_edge(2,S,0,0);
    for(int i=1;i<=n;i++){
        add_edge(1,i+2,1,-A[i]);add_edge(i+2,1,0,A[i]);
        add_edge(2,i+2,1,-B[i]);add_edge(i+2,2,0,B[i]);
        add_edge(i+2,T,1,0);add_edge(T,i+2,0,0);
        add_edge(i+2,T,1,A[i]*B[i]);add_edge(T,i+2,0,-A[i]*B[i]);
    }
    while(spfa());
    printf("%.4lf",-ans);
    return 0;
}

原文地址:https://www.cnblogs.com/Xu-daxia/p/10436202.html

时间: 2024-10-08 14:55:10

CF739E Gosha is hunting(费用流,期望)的相关文章

cf739E Gosha is hunting (flows)

739E 有$a$个普通球,$b$个超级球,有$n$个要捕捉的宝可梦,对于第$i$个宝可梦普通球的捕捉概率是$p_i$,超级球的捕捉概率是$u_i$,每种球只能扔一个到同一个宝可梦,同一个宝可梦可以被扔两种球.然后问在最优策略下捕捉个数的期望 考虑概率$dp$,发现状态无法简化到$n^2$级别,原来不是dp 假定每个宝可梦只能被扔一个球,那就是个匹配问题了,设$A$为普通球,$B$为超级球,源点向$A$,$B$连容量为球的个数,花费为$0$的边,$A,B$分别向每个精灵连容量为$1$,花费为$p

CF739E Gosha is hunting 【WQS二分 + 期望】

题目链接 CF739E 题解 抓住个数的期望即为概率之和 使用\(A\)的期望为\(p[i]\) 使用\(B\)的期望为\(u[i]\) 都使用的期望为\(p[i] + u[i] - u[i]p[i]\) 当然是用越多越好 但是他很烦地给了个上限,我们就需要作出选择了 有一个很明显的\(O(n^3)\)的\(dp\),显然过不了 但我们有一个很好的\(WQS\)二分 我们非常想去掉这个上限 那就去掉吧,但是每用一次都要付出一个代价 我们二分这个代价,当使用次数恰好为为\(a\)和\(b\)时就是

CF739E Gosha is hunting

法一: 匹配问题,网络流! 最大费用最大流,S到A,B流a/b费0,A,B到i流1费p[i]/u[i],同时选择再减p[i]*u[i]? 连二次!所以i到T流1费0流1费-p[i]*u[i] 最大流由于ab都选择完最优 最大费用,所以不会第一次走-p[i]*u[i] 法二: DP怎么写? dp[i][j][k] 优化? 一定选择a.b个! 恰好选择a.b个? WQS二分! 一定是满足凸函数的性质的 所以选择若干个a,代价ca,求dp[i][b] 再次WQS二分! 所以选择若干个a,b,代价ca,

CF739E Gosha is hunting DP+wqs二分

我是从其他博客里看到这题的,上面说做法是wqs二分套wqs二分?但是我好懒呀,只用了一个wqs二分,于是\(O(nlog^2n)\)→\(O(n^2logn)\) 首先我们有一个\(O(n^3)\)的暴力\(DP\),转移好写,形式优美,但复杂度不对 该怎样发现它的凸性质呢 1.打表√ 2.冷静分析一波,每一种球肯定是越多越好,于是我们先固定选择\(a\)个普通球,然后那\(b\)个大师球肯定是从大到小挑选.这样的话每多选一个,新增的收益就会下降一点,也就是说这是个上凸函数.(口胡如果假的话,就

【CF739E】Gosha is hunting 贪心

[CF739E]Gosha is hunting 题意:有n个小精灵,你有a个普通球和b个超级球,用普通球抓住第i只小精灵的概率为$A_i$,用超级球抓住第i只小精灵的概率为$u_i$.你必须一开始就决定向哪些精灵投掷哪些精灵球,同种的球只能对一个精灵用一次,可以对一只精灵投掷两种球,如果两次中有一次抓到则视为抓到.问你如果采用最优的方案,最终抓到小精灵的期望个数是多少. $n\le 2000$. 题解:我们先将所有小精灵按$B$排序,然后我们枚举最后一个投b或ab的小精灵i,那么不难证明i左边

Codeforces739E Gosha is hunting

题意:现在有n个精灵,两种精灵球各m1和m2个,每个精灵单独使用第一种精灵球有pi的概率被捕获,单独使用第二种精灵球有ui的概率被捕获,同时使用有1-(1-pi)*(1-ui)的概率被捕获.一种精灵球在一个精灵身上只能用一次,但你可以在一个精灵上用两种精灵球.求最优策略下期望获得精灵的只数. 如果一只精灵上不能同时用两种精灵球,那么就是一个显然的费用流建图,点A表示第一种精灵球,点B表示第二种精灵球,源点向A,B各连一条流量等于对应精灵球数目的边(费用为0),A,B分别向每个精灵连一条流量为1,

有上下界的、有多组源汇的、网络流、费用流问题

先默认读者有基础的网络流以及费用流的知识前置 1.有上下界无源点汇点的可行流问题: 在本文中指: 原图中没有任何一个点可以凭空产生流量,亦没有任何一个点可以凭空消灭流量: 存在边既有流量上界又有流量下界: 求每条边流量的一组可行解: 满足每个点的入流量等于出流量: 由题意可见本题的图中有环,于是此类问题也被称作循环流: 这里给出的解法是将本题转换为一道普通的有上界最大流问题: 修改本题原图中每条边的流量下界为0,上界为原上界-原下界: 视为该边现在已经拥有了等同于该边流量下界的基础流量了, 然而

【网络流24题】No.19 负载平衡问题 (费用流)

[题意] G 公司有 n 个沿铁路运输线环形排列的仓库, 每个仓库存储的货物数量不等. 如何用最少搬运量可以使 n 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入文件示例input.txt517 9 14 16 4 输出文件示例output.txt11 [分析] 其实我觉得这题可以贪心啊..n^2贪心??.没细想.. 打的是费用流.. 大概这样建图: 懒得写了..凌乱之美.. 求满流费用.. 1 #include<cstdio> 2 #include<cstdlib&

POJ 3422 kaka&#39;s matrix trvals(费用流)

#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include <map> #include <cma