【专题】概率期望DP
11.22:保持更新状态:主要发一些相关的题目和个人理解
(P.S.如果觉得简单,可以直接看后面的题目)
upd 11.30 更完了
【NO.1】
一道比较坑的题目,多给了一个没用的条件...其实就是利用线性关系,取一个平均值就OK了。
把最优情况和最差情况算出来,取一个算数平均值算出期望就OK了,应该是最简单的一道题了,关键是要想得到
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
char chr=getchar(); int f=,ans=;
while(!isdigit(chr)) {if(chr=='-') f=-;chr=getchar();}
while(isdigit(chr)) {ans=(ans<<)+(ans<<);ans+=chr-'';chr=getchar();}
return ans*f;
}
void write(int x){
if(x<) putchar('-'),x=-x;
if(x>) write(x/);
putchar(x%+'');
}
int n,d,p,i=;
double ans=;
int main(){
while(n=read(),d=read(),n||d){
++i;ans=;int k=;
while(n--){
int x=read(),y=read(),z=read();
k+=y;
ans+=2.0*y/z;
}ans+=d-k;
printf("Case %d: %.3lf\n\n",i,ans);
}
return ;
}
【NO.2】
SP1026 FAVDICE - Favorite Dice
其实这是一道赠券收集问题,这个看懂了之后,其实就很简单了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
char chr=getchar(); int f=,ans=;
while(!isdigit(chr)) {if(chr=='-') f=-;chr=getchar();}
while(isdigit(chr)) {ans=(ans<<)+(ans<<);ans+=chr-'';chr=getchar();}
return ans*f;
}
void write(int x){
if(x<) putchar('-'),x=-x;
if(x>) write(x/);
putchar(x%+'');
}
int n;
int main(){
n=read();
while(n--){
int x=read();
double ans=;
for(int i=;i<=x;i++){
ans+=x*1.0/(x-i+);
}
printf("%.2lf\n",ans);
}
return ;
}
中间小结:我们发现一个特性,代码很短,然而需要一定脑回路,想通了肯能5min就解决了,否则可能会想的很复杂(比如有一次码一百多行,后来发现可以O(1)时间一行直接输出...)
upd:11.26
【NO.3】
KIDS AND PRIZES
P.S. 额...这道题找不到来源,具体是SGU495,但是SGU消失了,Vjudge又不能提交,如果有读者知道怎么提交的话,可以在下面回复一下,谢谢
【题目描述】
n个盒子里装有礼物,m个人随机选择礼物,选完之后空盒子放回
问选中的礼物数的期望。
【思路】
有log(m)的做法(快速幂),在这里先介绍O(m)的做法
令dp[i]表示第i个人去箱子时的得到礼物的概率,那么有方程:
dp[1]=1,dp[i(i>1)]=dp[i-1]*(1-dp[i-1])+dp[i-1]*(dp[i-1]-1.0/n);
关于优化:
对上式进行化简,则有
dp[i]=dp[i-1]*(1-1.0/n)
不难发现1.0/n是一个常数 然后用数列的知识一顿瞎搞->dp[n]=(1-1.0/n)^m-1;
ans=∑dp[i]=n-n*((n-1)/n)^m
然后快速幂就好了
下面代码是O(m)的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
char chr=getchar(); int f=,ans=;
while(!isdigit(chr)) {if(chr=='-') f=-;chr=getchar();}
while(isdigit(chr)) {ans=(ans<<)+(ans<<);ans+=chr-'';chr=getchar();}
return ans*f;
}
void write(int x){
if(x<) putchar('-'),x=-x;
if(x>) write(x/);
putchar(x%+'');
}
int n,m;
double dp[],ans;
int main(){
n=read(),m=read();
dp[]=;
for(int i=;i<=m;i++)
dp[i]=dp[i-]*(-dp[i-])+dp[i-]*(dp[i-]-1.0/n),ans+=dp[i];
printf("%.5lf",ans+);
return ;
} 啦啦啦~~
感觉有点写不下去了...难受,关键是找不到一些题目...
【NO.4】
ZOJ3640 help me escape
题目描述
英语不太好,翻译不来,用机翻吧...这里就不给出了(懒..)
【思路】
记忆化搜索是个好东西,其实用记忆化搜索做这种题有时候更方便呢...
如果i>c[j] dp[i]+=(int)(p*c[j]*c[j])/n;
如果i<=c[j] dp[i]+=(dfs(i+c[j])+1)/n;
P.S.注意向下取整!!!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline double read(){
char chr=getchar(); int f=,ans=;
while(!isdigit(chr)) {if(chr=='-') f=-;chr=getchar();}
while(isdigit(chr)) {ans=(ans<<)+(ans<<);ans+=chr-'';chr=getchar();}
return ans*f*1.0;
}
void write(int x){
if(x<) putchar('-'),x=-x;
if(x>) write(x/);
putchar(x%+'');
}
int n,m;
double dp[];
int a[],b[];
const double t=(sqrt(5.0)+1.0)/2.0;
double dfs(int sum){
if(dp[sum]>) return dp[sum];
for(int i=;i<=n;i++){
if(sum>a[i])
dp[sum]+=(double)b[i]/n;
else dp[sum]+=(dfs(sum+a[i])+1.0)/n;
}
return dp[sum];
}
int main(){
while(~scanf("%d%d",&n,&m)){
memset(dp,,sizeof(dp));
for(int i=;i<=n;i++)cin>>a[i],b[i]=a[i]*a[i]*t;
double ans=dfs(m);
printf("%.3lf\n",ans);
}
return ;
}
后面的题目会偏难一点噢.
upd:11.29
好吧,其实也不是很难。。。暴力枚举状态然后转移就好了
前面的题目看懂的话,这道题可以直接上代码了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
char chr=getchar(); int f=,ans=;
while(!isdigit(chr)) {if(chr=='-') f=-;chr=getchar();}
while(isdigit(chr)) {ans=(ans<<)+(ans<<);ans+=chr-'';chr=getchar();}
return ans*f;
}
void write(int x){
if(x<) putchar('-'),x=-x;
if(x>) write(x/);
putchar(x%+'');
}
double f[][][][];
int T,n,a1,a2,a3;
double solve(){
double ans=;
f[][a1][a2][a3]=;
for(int i=;i<n;i++)
for(int a=;a<=;a++)
for(int b=;b<=;b++)
for(int c=;c<=;c++){
if(a+b+c>) continue;
if(a>)f[i+][a-][b][c]+=(double)f[i][a][b][c]*(double)a/(double)(a+b+c+);
if(b>&&a+b+c==)f[i+][a+][b-][c]+=f[i][a][b][c]*(double)b/(double)(a+b+c+);
if(b>&&a+b+c<) f[i+][a+][b-][c+]+=f[i][a][b][c]*(double)b/(double)(a+b+c+);
if(c>&&a+b+c==) f[i+][a][b+][c-]+=f[i][a][b][c]*(double)c/(double)(a+b+c+);
if(c>&&a+b+c<) f[i+][a][b+][c]+=f[i][a][b][c]*(double)c/(double)(a+b+c+);
f[i+][a][b][c]+=f[i][a][b][c]/(double)(a+b+c+);
ans+=f[i][a][b][c]/(double)(a+b+c+);
}printf("%.2lf\n",ans);
} int main(){
T=read();
while(T--){memset(f,,sizeof(f));
n=read(),a1=read(),a2=read(),a3=read();solve();
}
return ;
}
最后一道
刷表法就好了,有个技巧就是可以先排序一下,然后就能保证所有背包先被处理(因为与顺序无关,上面的“依次”是骗人的)
f[i][j][k] 表示第i个挑战,赢了j次,背包容量为k,还是暴力枚举状态枚举
具体可以见代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
char chr=getchar(); int f=,ans=;
while(!isdigit(chr)) {if(chr=='-') f=-;chr=getchar();}
while(isdigit(chr)) {ans=(ans<<)+(ans<<);ans+=chr-'';chr=getchar();}
return ans*f;
}
void write(int x){
if(x<) putchar('-'),x=-x;
if(x>) write(x/);
putchar(x%+'');
}
int n,l,k;
struct P{double p;int a;}a[];//概率 属性
double f[][][];
bool cmp(const P &x,const P &b){return x.a>b.a;}
int main(){
n=read(),l=read(),k=read();
for(int i=;i<=n;i++) cin>>a[i].p,a[i].p/=100.0;
for(int i=;i<=n;i++) cin>>a[i].a;
sort(a+,a+n+,cmp);
f[][][min(,k)]=;
for(int i=;i<n;i++)
for(int j=;j<=i;j++)
for(int k=;k<=n;k++){
f[i+][j][k]+=f[i][j][k]*(1.0-a[i+].p);//失败
int v=k+a[i+].a;
if(v<) continue;v=min(n,v);
f[i+][j+][v]+=f[i][j][k]*a[i+].p;//成功
}
double ans=;
for(int i=l;i<=n;i++)
for(int j=;j<=n;j++)
ans+=f[n][i][j];
printf("%.6lf",ans);
return ;
}
【专题】概率期望DP的更多相关文章
- 【BZOJ-1419】Red is good 概率期望DP
1419: Red is good Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 660 Solved: 257[Submit][Status][Di ...
- 【bzoj4832】[Lydsy2017年4月月赛]抵制克苏恩 概率期望dp
题目描述 你分别有a.b.c个血量为1.2.3的奴隶主,假设英雄血量无限,问:如果对面下出一个K点攻击力的克苏恩,你的英雄期望会受到到多少伤害. 输入 输入包含多局游戏. 第一行包含一个整数 T (T ...
- 【loj6191】「美团 CodeM 复赛」配对游戏 概率期望dp
题目描述 n次向一个栈中加入0或1中随机1个,如果一次加入0时栈顶元素为1,则将这两个元素弹栈.问最终栈中元素个数的期望是多少. 输入 一行一个正整数 n . 输出 一行一个实数,表示期望剩下的人数, ...
- Codeforces - 1264C - Beautiful Mirrors with queries - 概率期望dp
一道挺难的概率期望dp,花了很长时间才学会div2的E怎么做,但这道题是另一种设法. https://codeforces.com/contest/1264/problem/C 要设为 \(dp_i\ ...
- 概率期望dp
对于概率dp,我一直都弄得不是特别明白,虽然以前也有为了考试去突击过,但是终究还是掌握得不是很好,所以决定再去学习一遍,把重要的东西记录下来. 1.hdu4405 Description 在一个 \( ...
- Codeforces 908 D.New Year and Arbitrary Arrangement (概率&期望DP)
题目链接:New Year and Arbitrary Arrangement 题意: 有一个ab字符串,初始为空. 用Pa/(Pa+Pb)的概率在末尾添加字母a,有 Pb/(Pa+Pb)的概率在末尾 ...
- [BZOJ4832]抵制克苏恩(概率期望DP)
方法一:倒推,最常规的期望DP.f[i][a][b][c]表示还要再攻击k次,目前三种随从个数分别为a,b,c的期望攻击英雄次数,直接转移即可. #include<cstdio> #inc ...
- LightOJ 1030 Discovering Gold (概率/期望DP)
题目链接:LightOJ - 1030 Description You are in a cave, a long cave! The cave can be represented by a \(1 ...
- 【POJ 2096】Collecting Bugs 概率期望dp
题意 有s个系统,n种bug,小明每天找出一个bug,可能是任意一个系统的,可能是任意一种bug,即是某一系统的bug概率是1/s,是某一种bug概率是1/n. 求他找到s个系统的bug,n种bug, ...
随机推荐
- Python 之糗事百科多线程爬虫案例
import requests from lxml import etree import json import threading import queue # 采集html类 class Get ...
- 为Unity的新版ugui的Prefab生成预览图
using UnityEngine;using System.Collections;using UnityEditor;using System.IO; [CustomPreview(typeof( ...
- 安装hiredis后swoole扩展消失
php -m报错: PHP Warning: PHP Startup: Unable to load dynamic library 'swoole' (tried: /home/work/study ...
- 前端领域的BEM到底是什么
前端领域的BEM到底是什么 BEM - Block Element Modfier(块元素编辑器) BEM方法确保每一个参加了同一网站开发项目的人,基于一套代码规范去开发,这样非常有利于团队成员理解彼 ...
- Django - orm外键操作
1.orm外键操作 创建外键: 备注:ForeignKey两个参数,1个为关联的表名,1个为关联的字段名: 在django2.0后,定义外键和一对一关系的时候需要加on_delete选项,此参数为了避 ...
- 小白两篇博客熟练操作MySQL 之 第二篇
小白两篇博客熟练操作MySQL 之 第二篇 一. 视图 视图是一个虚拟表,其本质是根据SQL语句获取动态的数据集,并为其命名,用户使用时只需使用名称即可获取结果集, 并可以将其当做表来使用. s ...
- linux学习3-简单磁盘管理
简单的磁盘管理 下面涉及的命令具有一定的危险性,操作不当可能会丢失你的个人数据,初学者建议在虚拟环境中进行操作 通常情况下,这一小节应该直接将如何挂载卸载磁盘,如何格式化磁盘,如何分区,但如你所见,我 ...
- BUPT2017 springtraining(16) #4 ——基础数论
题目在这里 A.手动打表找规律得组合数 n -= 2, m -= 2, ans = C(n, m) #include <bits/stdc++.h> using namespace std ...
- POJ - 3538 - Domestic Networks
先上题目: Domestic Networks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 732 Accepted: ...
- 数字统计(2010年NOIP全国联赛普及组)
题目描述 请统计某个给定范围[L, R]的所有整数中,数字 2 出现的次数. 比如给定范围[2, 22],数字 2 在数 2 中出现了 1 次,在数 12 中出现 1 次,在数 20 中出 现 1 次 ...