题目传送门


题目描述

夏川的生日就要到了。作为夏川形式上的男朋友,季堂打算给夏川买一些生日礼物。
商店里一共有种礼物。夏川每得到一种礼物,就会获得相应喜悦值$W_i$(每种礼物的喜悦值不能重复获得)。
每次,店员会按照一定的概率$P_i$(或者不拿出礼物),将第i种礼物拿出来。季堂每次都会将店员拿出来的礼物买下来。没有拿出来视为什么都没有买到,也算一次购买。
众所周知,白毛切开都是黑的。所以季堂希望最后夏川的喜悦值尽可能地高。
求夏川最后最大的喜悦值是多少,并求出使夏川得到这个喜悦值,季堂的期望购买次数。


输入格式

第一行,一个整数N,表示有N种礼物。
接下来N行,每行一个实数$P_i$和正整数$W_i$,表示第i种礼物被拿出来的概率和可以获得喜悦值。


输出格式

第一行,一个整数表示可以获得的最大喜悦值。
第二行,一个实数表示获得这个喜悦值的期望购买次数,保留3位小数。


样例

样例输出:

3
0.1 2
0.2 5
0.3 7

样例输出:

14
12.167


数据范围与提示

对于10%的数据,N=1。
对于30%的数据,N≤5。
对于100%的数据,N≤20,$0<{W}_{i}≤{10}^{9}$,0<${P}_{i}$≤1且$\sum \limits_{i=1}^{n}{P}_{i}≤1$。


题意解释

又是血淋淋的没看懂题,再次印证了得语文者得OI,售货员一次只可能拿出一个礼物,且每个礼物只能买一次(捂脸……)


题解

偷偷看了看数据范围,喜悦值没有负值,于是乎,第一问就解决了,肯定是把所有礼物的喜悦值加起来。

那么来考虑10%的算法,N=1,我们只需要把这件礼物买下,且这件礼物的期望购买次数是$\frac{1}{P_i}$。

再来考虑30%的算法,那么每种商品都有买或不买两种状态,那么共有$2^N$种状态,$2^{{N}^{3}}$刚好跑过。

状态可以用状压(撞鸭)DP:设dp[S]表示当前状态为S,到买到所有礼物的期望步数。

剩下的那个$N^3$算法很容易想到高斯消元。

那么我们可以写出式子:

$dp[S]=\sum \limits_{i=1}^N P_i \times dp[S']+(1-\sum \limits_{i=1}^N P_i) \times dp[S]+1$

其中,S表示当前状态,S'为上一个状态,i表示没有买过的物品。

写出这个式子,你就跟正解不远了,把式子移个项:

$\sum \limits_{i=1}^N P_i \times dp[S]=\sum \limits_{i=1}^N P_i \times dp[S']+1\\dp[S]=\frac{\sum \limits_{i=1}^N P_i \times dp[S']+1}{\sum \limits_{i=1}^N P_i}$

这就是我们的DP式子啦,时间复杂度$O(2^N)$。

注意HDU输入格式不同,而且是special judge,记得输出时多保留一位即可(跟HDU数据刚了一下午,才发现是special judge,心态瞬间爆炸……)。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n;
double p[21];
long long w[21];//记得开long long
double dp[2000000];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lf%lld",&p[i],&w[i]);
p[0]+=p[i];
w[0]+=w[i];
}
printf("%lld\n",w[0]);//第一问
for(int i=(1<<n)-2;i>=0;i--)//dp
{
double flag=0.0;//分母
for(int j=1;j<=n;j++)
{
if((1<<(j-1))&i)continue;
dp[i]+=p[j]*dp[i|1<<(j-1)];
flag+=p[j];
}
dp[i]=(dp[i]+1.0)/flag;
}
cout<<fixed<<setprecision(3)<<dp[0]<<endl;//保留小数输出第二问
return 0;
}

HDU代码:

#include<bits/stdc++.h>
using namespace std;
int n;
double p[21];
double dp[2000000];
int main()
{
while(~scanf("%lld",&n))
{
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
scanf("%lf",&p[i]);
for(int i=(1<<n)-2;i>=0;i--)
{
double flag=0.0;
for(int j=1;j<=n;j++)
{
if((1<<(j-1))&i)continue;
dp[i]+=p[j]*dp[i|1<<(j-1)];
flag+=p[j];
}
dp[i]=(dp[i]+1.0)/flag;
}
cout<<fixed<<setprecision(4)<<dp[0]<<endl;//注意HDU是special judge
}
return 0;
}

rp++

[HDU4336]:Card Collector(概率DP)的更多相关文章

  1. hdu4336 Card Collector(概率DP,状态压缩)

    In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, fo ...

  2. hdu4336 Card Collector 概率dp(或容斥原理?)

    题意: 买东西集齐全套卡片赢大奖.每个包装袋里面有一张卡片或者没有. 已知每种卡片出现的概率 p[i],以及所有的卡片种类的数量 n(1<=n<=20). 问集齐卡片需要买东西的数量的期望 ...

  3. HDU-4336 Card Collector 概率DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4336 题意:买食品收集n个卡片,每个卡片的概率分别是pi,且Σp[i]<=1,求收集n个卡片需要 ...

  4. HDU4336 Card Collector (概率dp+状压dp)

    http://acm.hdu.edu.cn/showproblem.php?pid=4336 题意:有n种卡片,一个包里会包含至多一张卡片,第i种卡片在某个包中出现的次数为pi,问将所有种类的卡片集齐 ...

  5. $HDU$ 4336 $Card\ Collector$ 概率$dp$/$Min-Max$容斥

    正解:期望 解题报告: 传送门! 先放下题意,,,已知有总共有$n$张卡片,每次有$p_i$的概率抽到第$i$张卡,求买所有卡的期望次数 $umm$看到期望自然而然想$dp$? 再一看,哇,$n\le ...

  6. hdu4336 Card Collector 状态压缩dp

    Card Collector Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...

  7. HDU 4336 Card Collector 期望dp+状压

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4336 Card Collector Time Limit: 2000/1000 MS (Java/O ...

  8. [HDU4336]Card Collector(min-max容斥,最值反演)

    Card Collector Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  9. hdu 4336 Card Collector(期望 dp 状态压缩)

    Problem Description In your childhood, people in the famous novel Water Margin, you will win an amaz ...

随机推荐

  1. noip2018day1-赛道修建

    题目描述 \(C\) 城将要举办一系列的赛车比赛.在比赛前,需要在城内修建 $m $条赛道. \(C\) 城一共有 \(n\) 个路口,这些路口编号为 \(1,2,-,n\)有 $n-1 $条适合于修 ...

  2. phpstorm配置phpunit进行单元测试

    1.配置单元测试目录: (1)autoload.php <?php function autoloader($dir){ spl_autoload_register(function($name ...

  3. PyQt5_主要的类库

    1.PyQt5包括的主要模块如下. QtCore模块——涵盖了包的核心的非GUI功能,此模块被用于处理程序中涉及的时间.文件.目录.数据类型.文本流.链接.QMimeData.线程或进程等对象. Qt ...

  4. Java Calendar使用

    import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; impor ...

  5. 089、初探ELK (2019-05-13 周一)

    参考https://www.cnblogs.com/CloudMan6/p/7770916.html   在开源的日志管理方案中,最出名的莫过于ELK了.ELK是三个软件的合称: Elasticsea ...

  6. 10个用Java谋生非常有趣的方式

    令我惊讶的是,有些人觉得编程并不令人兴奋——只将它当作是一份枯燥的工作.不过,虽然可能的确有很多无聊的编程工作,但这并不意味着你不得不接受这些工作中的一个.程序员有各种各样的机会,运用他们的技能去做一 ...

  7. js 计算倒计时

    第一个是我自己写的 // t等于时间戳差 function changeTime(t) { let timeStr = '' let tmp = t/(24* 3600 * 1000) if (tmp ...

  8. FP Style 的快排

    const quickSort = (list) => { if (!list || !list.length) return []; if (list.length === 1) return ...

  9. 【Java】 ArrayList和LinkedList实现(简单手写)以及分析它们的区别

    一.手写ArrayList public class ArrayList { private Object[] elementData; //底层数组 private int size; //数组大小 ...

  10. Wannafly挑战赛22 B 字符路径 ( 拓扑排序+dp )

    链接:https://ac.nowcoder.com/acm/contest/160/B 来源:牛客网 题目描述 给一个含n个点m条边的有向无环图(允许重边,点用1到n的整数表示),每条边上有一个字符 ...