自不量力开始概率dp
文章目录
spoj favorite dice //倒推
题意:
一个骰子,n面,求每一面都被扔到至少一次的期望扔的次数。
思路:
d
p
[
i
]
:
已
经
扔
到
i
面
的
期
望
次
数
dp[i]:已经扔到i面的期望次数
dp[i]:已经扔到i面的期望次数
d
p
[
i
]
=
d
p
[
i
−
1
]
∗
n
−
i
+
1
n
+
d
p
[
i
]
∗
i
n
+
1
dp[i]=dp[i-1]*\frac{n-i+1}{n}+dp[i]*\frac{i}{n}+1
dp[i]=dp[i−1]∗nn−i+1+dp[i]∗ni+1
移向得:
d
p
[
i
]
=
d
p
[
i
−
1
]
+
n
n
−
i
+
1
dp[i]=dp[i-1]+\frac{n}{n-i+1}
dp[i]=dp[i−1]+n−i+1n
f
(
当
前
状
态
的
期
望
)
=
∑
(
f
(
能
转
移
过
来
的
状
态
的
期
望
)
∗
概
率
)
+
代
价
f(当前状态的期望)=\sum (f(能转移过来的状态的期望)*概率)+代价
f(当前状态的期望)=∑(f(能转移过来的状态的期望)∗概率)+代价
/* Author : Rshs
* Data : 2019-09-11-21.13
*/
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const LL mod = 1e9+7;
const int MX = 1e6+5;
double dp[MX];
void Main(int avg){
int n;cin>>n;
dp[0]=0;
for(int i=1;i<=n;i++) dp[i]=dp[i-1]+(1.0*n)/(1.0*n-1.0*i+1.0);
cout<<dp[n]<<'\n';
}
int main(){
int cas;cin>>cas;for(int i=1;i<=cas;i++)Main(i);
return 0;
}
LOOPS //二维倒推
题意:
一个人从(1,1)走到(n,m),当他在(i,j)时,可以花费2魔力施法,有p1几率原地不动,p2几率向右走,p3几率向下走。求到(n,m)的期望花费的魔力。
思路:
正
着
不
好
推
,
考
虑
倒
推
正着不好推,考虑倒推
正着不好推,考虑倒推。
d
p
[
i
]
[
j
]
:
从
(
i
,
j
)
到
(
n
,
m
)
的
期
望
,
d
p
[
n
]
[
m
]
=
0
dp[i][j]:从(i,j)到(n,m)的期望,dp[n][m]=0
dp[i][j]:从(i,j)到(n,m)的期望,dp[n][m]=0
d
p
[
i
]
[
j
]
=
2
+
d
p
[
i
]
[
j
]
∗
p
1
[
i
]
[
j
]
+
d
p
[
i
+
1
]
[
j
]
∗
p
2
[
i
]
[
j
]
+
d
p
[
i
]
[
j
+
1
]
∗
p
3
[
i
]
[
j
]
dp[i][j]=2+dp[i][j]*p1[i][j]+dp[i+1][j]*p2[i][j]+dp[i][j+1]*p3[i][j]
dp[i][j]=2+dp[i][j]∗p1[i][j]+dp[i+1][j]∗p2[i][j]+dp[i][j+1]∗p3[i][j]
移
向
得
:
d
p
[
i
]
[
j
]
=
(
2
+
d
p
[
i
+
1
]
[
j
]
∗
p
2
[
i
]
[
j
]
+
d
p
[
i
]
[
j
+
1
]
∗
p
3
[
i
]
[
j
]
)
/
(
1
−
p
1
[
i
]
[
j
]
)
移向得:dp[i][j]=(2+dp[i+1][j]*p2[i][j]+dp[i][j+1]*p3[i][j])/(1-p1[i][j])
移向得:dp[i][j]=(2+dp[i+1][j]∗p2[i][j]+dp[i][j+1]∗p3[i][j])/(1−p1[i][j])
这
里
注
意
p
1
[
i
]
[
j
]
=
=
1
时
候
,
直
接
c
o
n
t
i
n
u
e
.
这里注意p1[i][j]==1时候,直接continue.
这里注意p1[i][j]==1时候,直接continue.
保
证
有
解
,
说
明
走
到
这
种
点
的
概
率
为
0
保证有解,说明走到这种点的概率为0
保证有解,说明走到这种点的概率为0
/* Author : Rshs
* Data : 2019-09-12-15.15
*/
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const double eps = 1e-7;
const LL mod = 1e9+7;
const int MX = 1e3+5;
double p1[MX][MX],p2[MX][MX],p3[MX][MX],dp[MX][MX];
int main(){
int n,m;
while(cin>>n>>m){
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
scanf("%lf%lf%lf",&p1[i][j],&p2[i][j],&p3[i][j]);
dp[n][m]=0;
for(int i=n;i>=1;i--)for(int j=m;j>=1;j--){
if(i==n&&j==m)continue;
if(fabs(p1[i][j]-1)<=eps) {dp[i][j]=1e8;continue;} //不会走到这种点,但是需要continue
dp[i][j]=(2.0+dp[i][j+1]*p2[i][j]+dp[i+1][j]*p3[i][j])/(1.0-p1[i][j]);
}
printf("%.3lf\n",dp[1][1]);
}
return 0;
}
Help Me Escape //倒推
题
意
:
题意:
题意:
l
y
初
始
战
斗
力
为
f
,
l
y
周
围
有
n
条
路
,
每
条
路
上
有
一
个
妖
怪
,
战
斗
力
为
c
[
i
]
。
ly初始战斗力为f,ly周围有n条路,每条路上有一个妖怪,战斗力为c[i]。
ly初始战斗力为f,ly周围有n条路,每条路上有一个妖怪,战斗力为c[i]。
每
天
,
l
y
等
概
率
的
选
一
条
路
。
每天,ly等概率的选一条路。
每天,ly等概率的选一条路。
如
果
他
战
斗
力
大
于
c
[
i
]
,
那
么
他
花
t
[
i
]
天
就
可
以
逃
出
去
。
如果他战斗力大于c[i],那么他花t[i]天就可以逃出去。
如果他战斗力大于c[i],那么他花t[i]天就可以逃出去。
否
则
他
战
斗
力
变
为
f
+
c
[
i
]
,
等
明
天
再
战
。
否则他战斗力变为f+c[i],等明天再战。
否则他战斗力变为f+c[i],等明天再战。
求
l
y
逃
出
去
的
天
数
的
期
望
求ly逃出去的天数的期望
求ly逃出去的天数的期望
思
路
:
思路:
思路:
考
虑
倒
推
,
因
为
如
果
大
于
所
有
的
妖
怪
,
期
望
直
接
可
以
求
出
来
考虑倒推,因为如果大于所有的妖怪,期望直接可以求出来
考虑倒推,因为如果大于所有的妖怪,期望直接可以求出来
d
p
[
i
]
:
战
斗
力
为
i
时
,
逃
出
去
还
需
要
的
期
望
天
数
dp[i]:战斗力为i时,逃出去还需要的期望天数
dp[i]:战斗力为i时,逃出去还需要的期望天数
d
p
[
i
]
=
∑
j
=
1
n
i
>
c
[
j
]
?
t
[
j
]
:
(
d
p
[
i
+
c
[
j
]
]
+
1
)
n
dp[i]=\sum_{j=1}^n\frac{i>c[j]?t[j]:(dp[i+c[j]]+1)}{n}
dp[i]=∑j=1nni>c[j]?t[j]:(dp[i+c[j]]+1)
d
p
[
i
n
f
]
=
∑
j
=
1
n
t
[
j
]
n
dp[inf]=\sum_{j=1}^n\frac{t[j]}{n}
dp[inf]=∑j=1nnt[j]
/* Author : Rshs
* Data : 2019-09-12-16.00
*/
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const LL mod = 1e9+7;
const int MX = 1e6+5;
int c[105];
double t[105],dp[MX];
int main(){
int n,f;
while(cin>>n>>f){
int mx=2e4;
for(int i=1;i<=n;i++){
cin>>c[i];
t[i]=(int)(1.0*c[i]*c[i]*(1.0+sqrt(5))/2);
}
for(int i=mx;i>=f;i--){
dp[i]=0;
for(int j=1;j<=n;j++){
if(i>c[j]){
dp[i]=dp[i]+t[j]/(double)n; //成功
}
else {
dp[i]=dp[i]+(1.0+dp[i+c[j]])/(double)n; //失败
}
}
}
printf("%.3lf\n",dp[f]);
}
return 0;
}
hdu4035 Maze //循环解方程
题意:
n
n
n个节点的树,从结点1出发,到每个结点
i
i
i有三个事件:
1.
k
i
1.k_i
1.ki概率被杀死回到节点
1
1
1
2.
e
i
2.e_i
2.ei概率找到节点上面的出口逃出并胜利
3.
(
1
−
k
i
−
e
i
)
3.(1-k_i-e_i)
3.(1−ki−ei)概率下等概率走一条相连的边
求胜利所要走的步数的期望
思路:
神 仙 题 目 了 . . . . . . . 神仙题目了....... 神仙题目了.......
f ( i ) : 在 i 点 时 逃 出 所 需 要 的 期 望 次 数 f(i):在i点时逃出所需要的期望次数 f(i):在i点时逃出所需要的期望次数
叶 子 节 点 时 : 叶子节点时: 叶子节点时:
f ( i ) = e i ∗ 0 + k i ∗ f ( 1 ) + ( 1 − e i − k i ) ∗ ( f ( f a [ i ] ) + 1 ) f(i)=e_i*0+k_i*f(1)+(1-e_i-k_i)*(f(fa[i])+1) f(i)=ei∗0+ki∗f(1)+(1−ei−ki)∗(f(fa[i])+1)
f ( i ) = k i ∗ f ( 1 ) + ( 1 − e i − k i ) ∗ f ( f a [ i ] ) + 1 − e i − k i f(i)=k_i*f(1)+(1-e_i-k_i)*f(fa[i])+1-e_i-k_i f(i)=ki∗f(1)+(1−ei−ki)∗f(fa[i])+1−ei−ki
非 叶 子 节 点 : 非叶子节点: 非叶子节点:
f ( i ) = e i ∗ 0 + k i ∗ f ( 1 ) + ( 1 − e i − k i ) d i ∗ ( f ( f a [ i ] ) + 1 ) + ( 1 − e i − k i ) d i ∗ ( ∑ j ∈ s o n ( i ) ( f ( j ) + 1 ) ) f(i)=e_i*0+k_i*f(1)+\frac{(1-e_i-k_i)}{d_i}*(f(fa[i])+1)+\frac{(1-e_i-k_i)}{d_i}*(\sum_{j∈son(i)}(f(j)+1)) f(i)=ei∗0+ki∗f(1)+di(1−ei−ki)∗(f(fa[i])+1)+di(1−ei−ki)∗(∑j∈son(i)(f(j)+1))
f ( i ) = k i ∗ f ( 1 ) + ( 1 − e i − k i ) d i ∗ f ( f a [ i ] ) + ( 1 − e i − k i ) d i ∗ ( ∑ j ∈ s o n ( i ) f ( j ) ) + 1 − e i − k i ① f(i)=k_i*f(1)+\frac{(1-e_i-k_i)}{d_i}*f(fa[i])+\frac{(1-e_i-k_i)}{d_i}*(\sum_{j∈son(i)}f(j))+1-e_i-k_i \quad ① f(i)=ki∗f(1)+di(1−ei−ki)∗f(fa[i])+di(1−ei−ki)∗(∑j∈son(i)f(j))+1−ei−ki①
设 f ( i ) = a i ∗ f ( 1 ) + b i ∗ f ( f a [ i ] ) + c i . 设f(i)=a_i*f(1)+b_i*f(fa[i])+c_i. 设f(i)=ai∗f(1)+bi∗f(fa[i])+ci.
对 于 ① 式 : 对于①式: 对于①式:
f ( i ) = k i ∗ f ( 1 ) + ( 1 − e i − k i ) d i ∗ f ( f a [ i ] ) + ( 1 − e i − k i ) d i ∗ ( ∑ j ∈ s o n ( i ) ( a j ∗ f ( 1 ) + b j ∗ f ( f a [ j ] ) + c j ) ) + 1 − e i − k i f(i)=k_i*f(1)+\frac{(1-e_i-k_i)}{d_i}*f(fa[i])+\frac{(1-e_i-k_i)}{d_i}*(\sum_{j∈son(i)}(a_j*f(1)+b_j*f(fa[j])+c_j))+1-e_i-k_i f(i)=ki∗f(1)+di(1−ei−ki)∗f(fa[i])+di(1−ei−ki)∗(∑j∈son(i)(aj∗f(1)+bj∗f(fa[j])+cj))+1−ei−ki
因 为 f a [ j ] = i : 因为 fa[j]=i: 因为fa[j]=i:
f ( i ) = k i ∗ f ( 1 ) + ( 1 − e i − k i ) d i ∗ f ( f a [ i ] ) + ( 1 − e i − k i ) d i ∗ ( ∑ j ∈ s o n ( i ) ( a j ∗ f ( 1 ) + b j ∗ f ( i ) + c j ) ) + 1 − e i − k i f(i)=k_i*f(1)+\frac{(1-e_i-k_i)}{d_i}*f(fa[i])+\frac{(1-e_i-k_i)}{d_i}*(\sum_{j∈son(i)}(a_j*f(1)+b_j*f(i)+c_j))+1-e_i-k_i f(i)=ki∗f(1)+di(1−ei−ki)∗f(fa[i])+di(1−ei−ki)∗(∑j∈son(i)(aj∗f(1)+bj∗f(i)+cj))+1−ei−ki
把 右 边 的 f ( i ) 移 到 左 边 : 把右边的f(i)移到左边: 把右边的f(i)移到左边:
f ( i ) ∗ ( 1 − ( 1 − e i − k i ) d i ∗ ( ∑ j ∈ s o n ( i ) b j ) ) = f ( 1 ) ∗ ( k i + ( 1 − e i − k i ) d i ∗ ( ∑ j ∈ s o n ( i ) a j ) ) + ( 1 − e i − k i ) d i ∗ f ( f a [ i ] ) + 1 − e i − k i + ( 1 − e i − k i ) d i ∗ ( ∑ j ∈ s o n ( i ) c j ) f(i)*(1-\frac{(1-e_i-k_i)}{d_i}*(\sum_{j∈son(i)}b_j))=f(1)*(ki+\frac{(1-e_i-k_i)}{d_i}*(\sum_{j∈son(i)}a_j))+\frac{(1-e_i-k_i)}{d_i}*f(fa[i])+1-e_i-k_i+\frac{(1-e_i-k_i)}{d_i}*(\sum_{j∈son(i)}c_j) f(i)∗(1−di(1−ei−ki)∗(∑j∈son(i)bj))=f(1)∗(ki+di(1−ei−ki)∗(∑j∈son(i)aj))+di(1−ei−ki)∗f(fa[i])+1−ei−ki+di(1−ei−ki)∗(∑j∈son(i)cj)
可 得 : 可得: 可得:
a i = k i + ( 1 − e i − k i ) d i ∗ ( ∑ j ∈ s o n ( i ) a j ) 1 − ( 1 − e i − k i ) d i ∗ ( ∑ j ∈ s o n ( i ) b j ) a_i=\frac{k_i+\frac{(1-e_i-k_i)}{d_i}*(\sum_{j∈son(i)}a_j)}{1-\frac{(1-e_i-k_i)}{d_i}*(\sum_{j∈son(i)}b_j)} ai=1−di(1−ei−ki)∗(∑j∈son(i)bj)ki+di(1−ei−ki)∗(∑j∈son(i)aj)
b i = ( 1 − e i − k i ) d i 1 − ( 1 − e i − k i ) d i ∗ ( ∑ j ∈ s o n ( i ) b j ) b_i=\frac{\frac{(1-e_i-k_i)}{d_i}}{1-\frac{(1-e_i-k_i)}{d_i}*(\sum_{j∈son(i)}b_j)} bi=1−di(1−ei−ki)∗(∑j∈son(i)bj)di(1−ei−ki)
c i = 1 − e i − k i + ( 1 − e i − k i ) d i ∗ ( ∑ j ∈ s o n ( i ) c j ) 1 − ( 1 − e i − k i ) d i ∗ ( ∑ j ∈ s o n ( i ) b j ) c_i=\frac{1-e_i-k_i+\frac{(1-e_i-k_i)}{d_i}*(\sum_{j∈son(i)}c_j)}{1-\frac{(1-e_i-k_i)}{d_i}*(\sum_{j∈son(i)}b_j)} ci=1−di(1−ei−ki)∗(∑j∈son(i)bj)1−ei−ki+di(1−ei−ki)∗(∑j∈son(i)cj)
这 时 候 一 个 神 奇 的 地 方 , 对 于 叶 子 节 点 这时候一个神奇的地方,对于叶子节点 这时候一个神奇的地方,对于叶子节点:
a i = k i , b i = 1 − e i − k i , c i = 1 − e i − k i a_i=k_i,b_i=1-e_i-k_i,c_i=1-e_i-k_i ai=ki,bi=1−ei−ki,ci=1−ei−ki
那 么 从 叶 子 节 点 开 始 求 , 不 停 递 归 回 根 节 点 . 那么从叶子节点开始求,不停递归回根节点. 那么从叶子节点开始求,不停递归回根节点.
∵ f ( 1 ) = a 1 ∗ f ( 1 ) + c 1 ∴ f ( 1 ) = c 1 1 − a 1 ∵ f(1)=a_1*f(1)+c_1\quad\quad∴f(1)=\frac{c_1}{1-a_1} ∵f(1)=a1∗f(1)+c1∴f(1)=1−a1c1
这 里 判 断 无 解 的 条 件 : a 1 趋 近 于 1 这里判断无解的条件:a_1趋近于1 这里判断无解的条件:a1趋近于1
/* Author : Rshs
* Data : 2019-09-12-19.20
*/
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const double eps = 1e-9;
const LL mod = 1e9+7;
const int MX = 1e5+5;
double e[MX],k[MX];
double a[MX],b[MX],c[MX],aa[MX],bb[MX],cc[MX];
vector<int>g[MX];
void dfs(int v,int fa){
aa[v]=bb[v]=cc[v]=0;
for(auto i:g[v]){
if(i==fa) continue;
dfs(i,v);
aa[v]+=a[i];bb[v]+=b[i];cc[v]+=c[i];
}
double zz=(1.0-e[v]-k[v])/(1.0*SZ(g[v]));
a[v]=(k[v]+zz*aa[v])/(1.00-zz*bb[v]);
b[v]=zz/(1.0-zz*bb[v]);
c[v]=(1.0-e[v]-k[v]+zz*cc[v])/(1.0-zz*bb[v]);
}
void Main(int avg){
int n;cin>>n;
for(int i=1;i<=n;i++)g[i].clear();
for(int i=1;i<n;i++){
int sa,sb;scanf("%d%d",&sa,&sb);
g[sa].push_back(sb);g[sb].push_back(sa);
}
for(int i=1;i<=n;i++)scanf("%lf%lf",&k[i],&e[i]),k[i]/=100.0,e[i]/=100.0;
dfs(1,-1);
printf("Case %d: ",avg);
if(fabs(a[1]-1)<eps) {puts("impossible");return;}
printf("%lf\n",c[1]/(1-a[1]));
}
int main(){
int cas;cin>>cas;for(int i=1;i<=cas;i++)Main(i);
return 0;
}
Bloodsucker //组合数
题目
题意:
n
n
n个人,一开始有一个吸血鬼,每天随机的从
n
n
n个人中挑出两个人,如果一个人是吸血鬼,一个人是普通人,那么普通人有
p
p
p的概率被感染,求全部人变成吸血鬼的期望天数。
思路:
定
义
d
p
[
i
]
:
有
i
个
吸
血
鬼
时
,
全
部
变
成
吸
血
鬼
的
期
望
天
数
,
d
p
[
n
]
=
0.
定义dp[i]:有i个吸血鬼时,全部变成吸血鬼的期望天数,dp[n]=0.
定义dp[i]:有i个吸血鬼时,全部变成吸血鬼的期望天数,dp[n]=0.
第
i
天
感
染
一
个
人
的
概
率
为
:
z
=
i
∗
(
n
−
i
)
n
∗
(
n
−
1
)
/
2
.
第i天感染一个人的概率为:z=\frac{i*(n-i)}{n*(n-1)/2}.
第i天感染一个人的概率为:z=n∗(n−1)/2i∗(n−i).
d
p
[
i
]
=
(
1
+
d
p
[
i
+
1
]
)
∗
z
+
(
d
p
[
i
]
+
1
)
∗
(
1
−
z
)
,
然
后
移
项
即
可
dp[i]=(1+dp[i+1])*z+(dp[i]+1)*(1-z),然后移项即可
dp[i]=(1+dp[i+1])∗z+(dp[i]+1)∗(1−z),然后移项即可
/* Author : Rshs
* Data : 2019-09-13-15.27
*/
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const double eps = 1e-10;
const LL mod = 1e9+7;
const int MX = 1e6+5;
double dp[MX];
void Main(int avg){
int n;double p;
cin>>n>>p;
dp[n]=0;
for(int i=n-1;i>=1;i--){
double x=(1.0*n-i)*2/(1.0*n);
double y=1.0*i/(1.0*n-1);
dp[i]=(1.0+dp[i+1]*x*y*p)/(x*y*p);
}
printf("%.3lf\n",dp[1]);
}
int main(){
int cas;cin>>cas;for(int i=1;i<=cas;i++)Main(i);
return 0;
}
CF #105 Div.2 D. Bag of mice//概率,二维
题目
题意:
有
w
w
w个白老鼠,
b
b
b个黑老鼠,
l
y
ly
ly和
r
s
rs
rs博弈,先取到白老鼠的人获胜,
l
y
ly
ly先手。
当
r
s
rs
rs取的时候,会随机的跑掉一只老鼠。没人取到白老鼠
r
s
rs
rs获胜。
求
l
y
ly
ly获胜的期望.
思路:
定义
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
dp[i][j][k]
当
k
=
=
0
k==0
k==0时:剩下
i
i
i个白老鼠,
j
j
j个黑老鼠,轮到
l
y
ly
ly取老鼠的概率。
当
k
=
=
1
k==1
k==1时:剩下
i
i
i个白老鼠,
j
j
j个黑老鼠,轮到
r
s
rs
rs取老鼠的概率。
最后从
(
w
,
b
)
(w,b)
(w,b)倒推矩阵到
(
0
,
0
)
(0,0)
(0,0),期间累加ly获胜情况下的概率。
/* Author : Rshs
* Data : 2019-09-13-20.23
*/
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const double eps = 1e-10;
const LL mod = 1e9+7;
const int MX = 1e6+5;
double dp[1005][1005][2];
int main(){
int w,b;
cin>>w>>b;dp[w][b][0]=1;
double ans=0;
for(int i=w;i>=0;i--){
for(int j=b;j>=0;j--){
if(i==0&&j==0) continue;
double p=(i*1.00)/(1.0*i+j);
ans+=p*dp[i][j][0];
if(j>=1)dp[i][j-1][1]+=(1.0-p)*dp[i][j][0];
if(j>=2)dp[i][j-2][0]+=(1.0-p)*(1.0*j-1)/(1.0*j-1+i)*dp[i][j][1];
if(j>=1&&i>=1) dp[i-1][j-1][0]+=(1.0-p)*(1.0*i)/(1.0*j-1+i)*dp[i][j][1];
}
}
printf("%.12lf\n",ans);
return 0;
}