本来没有打算写题解的,时间有点紧。但是这个wqs二分看了好久才明白还是写点东西吧。

题解就直接粘dg的了:

赤(red)

本题来自codeforces 739E,加大了数据范围.

首先对一只猫不会扔两个及以上数量的同种食物。最优方案一定把食物用完.

每只猫对期望的贡献可以根据期望的线性性分开算的,不投喂,则这只猫贡献为0;

只喂干脆面,贡献为pi;只喂豆干,贡献为qi;两种都喂,贡献为pi+qi-pi*qi

算法1:

对于每只猫,只有4种情况,所以我们大力枚举一下,单组数据O(4^n),可以通过第1个测试点,期望得分10分。

算法2:

对于第2个测试点,有刚好等于猫数的豆干或干脆面,那么我们把等于猫数的食品一只猫喂一个,考虑每只猫多喂另一种食品后能新得到的贡献,例如,第i只猫已经喂了一个豆干,再喂一包干脆面对期望的贡献为(1-qi)*pi,可以认为不喜欢豆干时干脆面才会新产生贡献。我们排个序就好了,单组数据O(n+nlogn),结合算法1,期望得分20分.

算法3:

考虑DP,定义f[i][j][k]为前i只猫投喂j包干脆面和k包豆干时得到的最大期望猫数,转移时考虑第i只猫如何投喂,复杂度O(nab),可以通过1,2,3,4号测试点,期望得分40分。

算法4:

注意到第5个测试点的a和b都相当大,那么没有被投喂的猫就会相对较少,我们考虑对没有被投喂的猫进行DP。不妨先给所有的猫都同时投喂两种食品,然后再收回n-a包豆干和n-b包干脆面,最小化期望猫数的损失即可。DP和算法3类似,时间复杂度O(n(n-a)(n-b))结合算法3,期望得分50分。

第6到7个测试点是为复杂度较优的算法准备的。

算法5:

考虑网络流。给一只猫分配一包干脆面可以得到pi的收益,给一只猫分配一包豆干可以得到qi的收益,但同时分配这两种食品将损失pi*qi的收益.如果不考虑pi*qi的损失,有一个很明显的费用流建图:建两个点表示豆干和干脆面,从原点向这两个点分别连费用为0,流量等于对应食品数目的边,从干脆面向每只猫连流量为1,费用为pi的边,从豆干向每只猫连流量为1,费用为qi的边,从每只猫向汇点连流量为2,费用为0的边。那么pi*qi的损失应当可以加到这个比较简单的模型的某一条边上。聪明的你一定想到了,我们把从猫连向汇点的边拆成两条,流量均为1,但一条费用为0,一条费用为-pi*qi,这样跑出来就是对的。

时间复杂度O(费用流).

期望得分70分

算法6:

cf官方题解的方法,用数据结构维护贪心。可见这个题并没有考网络流

期望得分70分

算法7

这是一种被称作Wqs二分(wqs=王钦石)的黑科技。熟悉wqs二分的选手可以直接去看算法8了.

假设看这里的选手没有听说过wqs二分.

考虑如何优化算法3的O(n^3)DP.

我们首先不考虑b的限制,假设豆干可以任意使用,定义f[i][j]表示前i只猫使用j包干脆面和若干包豆干得到的最大收益。直接这么DP会n只猫都用豆干,可能会超出b的限制。

为了减少豆干的使用,我们可以假定使用一个豆干需要额外付出cost的代价(也就是在转移的时候如果一只猫用了豆干,它对期望值的贡献要减去cost).在DP的时候,求解出f[i][j]的最大值,并记录最优方案中豆干使用的数目x,那么此时真实的期望是f[i][j]的最优值加上x*cost,这个结果必然也是用了x个 豆干时能够得到的最优结果.

但是,如果我们随便假定一个cost去跑DP,得到的方案并不一定把所有豆干都用完,我们需要一个能把所有豆干都用完的cost的值.

显然豆干使用量随着cost的变化是单调变化的,我们可以二分cost的数值.

时间复杂度O(n2logn)

期望得分70分.

算法8(满分算法)

我们还可以做到O(nlog2n),具体做法在算法7的基础上,wqs二分套wqs二分,把DP再减少一维。假设用豆干有cost1的额外花费,用干脆面有cost2的额外花费.f[i]表示前i只猫的最大收益.然后外层二分cost1内层二分cost2.

看标程理解一下吧.

这个做法当然不是lrd想出来的啦.

出处:http://codeforces.com/blog/entry/49691

出题人的预测:NOIP水平的选手拿到本题的前50分就不错了.这50分应当还是有区分度的.水平稍高的选手可能打出一种复杂度较好的算法拿到70分.满分做法应当是相当难想到的.

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define int long long
#define MP(a,b) make_pair(a,b)
using namespace std;
const double esp=1e-;
int n,a,b;
double p[],q[];
struct zt
{
int x,y;double val;
void clear(){x=val=y=;}
friend bool operator < (zt a,zt b)
{
if(a.val!=b.val)return a.val<b.val;
if(a.y!=b.y)return a.y>b.y;
return a.x>b.x;
}
}f[];
inline int read();
signed main()//清空
{
while(cin>>n>>a>>b)
{
for(int i=;i<=n;i++)scanf("%lf",&p[i]);
for(int i=;i<=n;i++)scanf("%lf",&q[i]); double L=,R=,cost1,ans=,cost2;
while(R-L>=esp)
{
cost1=(L+R)/;f[].clear(),f[].clear();
double l=,r=;zt res;res.clear();
while(r-l>=esp)
{
cost2=(l+r)/;f[].clear();f[].clear();
for(int i=;i<=n;i++)
{
int now=i%,pre=(i-)%;
f[now]=f[pre];double tv;
tv=f[pre].val+p[i]-cost1;
if(tv-f[now].val>=esp)f[now]=(zt){f[pre].x+,f[pre].y,tv};
tv=f[pre].val+q[i]-cost2;
if(tv-f[now].val>=esp)f[now]=(zt){f[pre].x,f[pre].y+,tv};
tv=f[pre].val+p[i]+q[i]-p[i]*q[i]-cost1-cost2;
if(tv-f[now].val>=esp)f[now]=(zt){f[pre].x+,f[pre].y+,tv};
}
int now=n%;
if(f[now].y<=b)res=max(res,f[now]),r=cost2;
else l=cost2;
if(f[now].y==b){res=f[now];break;}
}
if(res.x<=a)ans=max(ans,res.val+res.x*cost1+res.y*cost2),R=cost1;
else L=cost1;
if(res.x==a)break;
}
printf("%0.5lf\n",f[n%].val+a*cost1+b*cost2);
// printf("%0.5lf\n",ans);
}
}
inline int read()
{
int s=,f=;char a=getchar();
while(a<''||a>''){if(a=='-')f=-;a=getchar();}
while(a>=''&&a<=''){s=s*+a-'';a=getchar();}
return s*f;
}

dg的题解是真的详细,照着打应该不是很难。

但是关于wqs二分有一个细节好久才弄明白。

就是最后答案为什么是‘f[n%2].val+a*cost1+b*cost2’而不是‘f[n%2].val+f[n%2].x*cost1+f[n%2].y*cost2',明明只用了x包干脆面和y个豆干为什么要加上a,b的补充权值?

于是我在代码后面加了这个:‘if(f[n%2].x!=a||f[n%2].y!=b)puts("!!!!!!!!!!!1");’

最后求出来的x,y和a,b并不一样。但是显然都用完是最优的。问题在于可能并不存在一组cost1,cost2使得dp出来正好是都用完的,比如 所有的猫的p都相等而a<n,那么二分出来x要么是0要么是n。这种时候继续二分找到一个最贴近的补充权值cost1使得a*cost1最优。

大概就这些吧。

HZOJ 赤(CF739E Gosha is hunting)的更多相关文章

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

    题目链接 CF739E 题解 抓住个数的期望即为概率之和 使用\(A\)的期望为\(p[i]\) 使用\(B\)的期望为\(u[i]\) 都使用的期望为\(p[i] + u[i] - u[i]p[i] ...

  2. CF739E Gosha is hunting DP+wqs二分

    我是从其他博客里看到这题的,上面说做法是wqs二分套wqs二分?但是我好懒呀,只用了一个wqs二分,于是\(O(nlog^2n)\)→\(O(n^2logn)\) 首先我们有一个\(O(n^3)\)的 ...

  3. 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] 最大流由 ...

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

    根据期望的线性性答案就是捕捉每一只精灵的概率之和. 捕捉一只精灵的方案如下: 1.使用一个\(A\)精灵球,贡献为\(A[i]\) 2.使用一个\(B\)精灵球,贡献为\(B[i]\) 3.使用一个\ ...

  5. CF739E Gosha is hunting(费用流/凸优化dp)

    纪念合格考爆炸. 其实这个题之前就写过博客了,qwq但是不小心弄丢了,所以今天来补一下. 首先,一看到球的个数的限制,不难相当用网络流的流量来限制每个球使用的数量. 由于涉及到最大化期望,所以要使用最 ...

  6. 【CF739E】Gosha is hunting 贪心

    [CF739E]Gosha is hunting 题意:有n个小精灵,你有a个普通球和b个超级球,用普通球抓住第i只小精灵的概率为$A_i$,用超级球抓住第i只小精灵的概率为$u_i$.你必须一开始就 ...

  7. 【CF739E】Gosha is hunting(动态规划,凸优化)

    [CF739E]Gosha is hunting(动态规划,凸优化) 题面 洛谷 CF 题解 一个\(O(n^3)\)的\(dp\)很容易写出来. 我们设\(f[i][a][b]\)表示前\(i\)个 ...

  8. 【CF739E】Gosha is hunting(WQS二分套WQS二分)

    点此看题面 大致题意: 你有两种捕捉球(分别为\(A\)个和\(B\)个),要捕捉\(n\)个神奇宝贝,第\(i\)个神奇宝贝被第一种球捕捉的概率是\(s1_i\),被第二种球捕捉的概率是\(s2_i ...

  9. Codeforces739E Gosha is hunting

    题意:现在有n个精灵,两种精灵球各m1和m2个,每个精灵单独使用第一种精灵球有pi的概率被捕获,单独使用第二种精灵球有ui的概率被捕获,同时使用有1-(1-pi)*(1-ui)的概率被捕获.一种精灵球 ...

随机推荐

  1. Intent 传递Map数据

    android开发默认情况下,通过Bundle bundle=new Bundle();传递值是不能直接传递map对象的,解决办法: 第一步:封装自己的map,实现序列化即可 /** *序列化map供 ...

  2. url映射 ccf (Java正则表达式80分解法)

    问题描述 试题编号: 201803-3 试题名称: URL映射 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 URL 映射是诸如 Django.Ruby on Rails 等 ...

  3. vue项目及插件

    vue项目的创建 方法1: cmd中执行 vue ui vue会创建一个socket,方便快捷 方法2: 命令行建立 vue create v-proj //创建项目名为v-proj的项目文件 > ...

  4. Linux 基础命令3 shell

    echo 显示一行文本 各种展开的实例 波浪线展开 算术表达式展开 支持的运算 奇怪的花括号展开 花括号的..用法 花括号(任选一个)的嵌套 参数展开$符很重要哦(一种展开做另一种的参数) 命令的替换 ...

  5. 解决VC编译的DLL要安装对应运行环境否则无法使用的问题

    编译时候改成静态链接,再通过使用Depends软件查看依赖即可.具体操作步骤:项目->属性->配置属性->C/C++-代码生成->运行库->多线程(/MT)说明:这种方法 ...

  6. ML面试1000题系列(81-90)

    本文总结ML面试常见的问题集 转载来源:https://blog.csdn.net/v_july_v/article/details/78121924 81.已知一组数据的协方差矩阵P,下面关于主分量 ...

  7. DFA算法实现敏感词过滤

    DFA算法:即确定有穷自动机,简单点说就是,它是是通过event和当前的state得到下一个state,即event+state=nextstate.理解为系统中有多个节点,通过传递进入的event, ...

  8. VisualVM介绍使用

    1    打开VisualVM(这个工具放在JDK安装目录的bin目录下,双击jvisualvm.exe即可打开),如下图所示 以VisualVM自身为例,VisualVM本身也是一个java程序,当 ...

  9. 技巧专题3(cdq分治、整体二分等)

    cdq分治与整体二分 cdq来源于2008年国家集训队作业陈丹琦(雅礼巨佬),用一个log的代价完成从静态到动态(很多时候是减少时间那一维的). 对于一个时间段[L, R],我们取mid = (L + ...

  10. JavaScript--关于实例对象带不带参数和构造函数带不带参数的关系

    就是一句话: 构造函数创建对象时,也可以带参数,因为可以对对象进行一些属性的初始化,也就是你创建对象时,就带着这些属性,当然你也可以不带参数,后面实例化对象后再进行添加.而且,js函数的参数在定义函数 ...