您的位置:首页 > 其它

[bzoj4832]抵制克苏恩 概率dp

2017-07-30 19:51 375 查看
考试的时候打了个搜索,时间比较短,样例又非常的弱,实在不太清楚他这个到底是什么意思。

不过lc大神好腻害,讲解了一下非常的清楚了。

f[i][j][k][l]表示第i次伤害(啊),一滴血j个,两滴血k个,三滴血l个的概率。

初始状态f[1][a][b][c]=1

转移状态

1.此次攻击英雄 f[i+1][j][k][l]

2.攻击一个血量为1的仆从→ f[i+1][j-1][k][l]

3.攻击一个血量为2的仆从→ f[i+1][j+1][k-1][l]//超过7个仆从    f[i+1][j+1][k-1][l+1]//不超过7个

4.攻击一个血量为3的仆从→ f[i+1][j][k+1][l-1]//超过7个仆从    f[i+1][j][k+1][l]//不超过7个

那么最后答案应为Σf[i][j][k][l]*1.0*1/(j+k+l+1)

注意:转移时候要看清转移概率的人数。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
#define N 60
double f

,ans;
int n,a,b,c;
int t;
int main(){
scanf("%d",&t);
while(t--){
memset(f,0,sizeof(f));
scanf("%d%d%d%d",&n,&a,&b,&c);
ans=0;
f[1][a][b][c]=1;
pos(i,1,n){
pos(j,0,7){
pos(k,0,7){
pos(l,0,7){
if(l+j+k<=7){
f[i][j][k][l]+=f[i-1][j][k][l]*(double)1/(j+k+l+1);
f[i][j][k][l]+=f[i-1][j+1][k][l]*(double)(j+1)/(j+k+l+2);
if(j!=0)
{
if((j+k+l)==7)
f[i][j][k][l]+=f[i-1][j-1][k+1][l]*(double)(k+1)/(j+k+l+1);
f[i][j][k][l]+=f[i-1][j-1][k+1][l-1]*(double)(k+1)/(j+k+l);
}
if(k!=0)
{
if((j+k+l)==7)
f[i][j][k][l]+=f[i-1][j][k-1][l+1]*(double)(l+1)/(j+k+l+1);
f[i][j][k][l]+=f[i-1][j][k-1][l]*(double)l/(j+k+l);
}
}
}
}
}
}
pos(i,1,n)
pos(j,0,7)
pos(k,0,7)
pos(l,0,7)
if((l+j+k)<=7)
ans+=f[i][j][k][l]*(double)1/(j+k+l+1);
printf("%0.2lf\n",ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  概率dp