#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
#define bug(x) cout<<#x<<"=="<<x<<endl;
double dp[1005][1005];
struct node
{
double yd;
double ydx;
double ydy;
}a[1005][1005];
int main()
{
int r,c;
while(scanf("%d %d",&r,&c)!=EOF)
{
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
scanf("%lf %lf %lf",&a[i][j].yd,&a[i][j].ydx,&a[i][j].ydy);
}
}
dp[r][c]=0;
for(int i=r;i>=1;i--)
{
for(int j=c;j>=1;j--)
{
if(a[i][j].yd==1.00||(i==r&&j==c))
{
continue;
}
dp[i][j]=(a[i][j].ydx*dp[i][j+1]+a[i][j].ydy*dp[i+1][j]+2)/(1.0-a[i][j].yd);
}
}
printf("%.3f\n",dp[1][1]);
}
}
/*#define mid (l+r)>>1
#define lr root*2
#define rr root*2+1
struct edge
{
int to,next;
}e[maxn*2];
int head[maxn] = { 0 };
int tot=0;
void add(int x,int y)
{
tot++;
e[tot]=(edge){y,head[x]};
head[x] = tot;
}
int dep[maxn],fa[maxn],siz[maxn];
///深度,父亲结点。子树大小
int son[maxn],dfn[maxn],top[maxn];
///重儿子,每一个结点通过冲链排序出来的顺序就是dfn也是他的dfs序,每一个结点所在的重链的顶点
int dfs1(int x,int Fa,int Dep)
{
dep[x]=Dep,fa[x]=Fa,siz[x]=1;
int maxson=1;///头结点
for(int i=head[x];~i;i=e[i].next)
{
siz[x] += dfs1(e[i].to,x,Dep+1);
if( siz[ e[i].to ] >maxson)
{
maxson = siz[ e[i].to ];
son[x] = e[i].to;
///记录最大的重儿子
}
}
return siz[x];
}
int cnt=0;///给每一个点标记编号
void dfs2(int x,int Top)
{
cnt++;
dfn[x]=cnt;
top[x]=Top;
if(!son[x])return ;
///叶子结点不需要计算啦
dfs2(son[x],Top);
for(int i=head[x];~i;i=e[i].next)
{
if(!dfn[ e[i].to ])
///说明e[i].to为x的轻儿子,他现在是自己子树的重链的起点,所以是Top
{
dfs2(e[i].to,e[i].to);
}
}
}
struct node
{
int l,r;
int w;
} tree[maxn*4];
inline void pushup(int root)
{
tree[root].w = tree[lr].w + tree[rr].w;
}
void build(int root,int l,int r)
{
tree[root].l = l;
tree[root].r = r;
if(l==r)
{
tree[root].w = 1;
return ;
}
build(lr,l,mid);
build(rr,mid+1,r);
pushup(root);
}
inline void update(int root,int p,int type)///将结点p的 w 修改为type
{
if(tree[root].l==tree[root].r)
{
tree[root].w=type;
return ;
}
int l=tree[root].l;
int r=tree[root].r;
if(p<=mid)
{
update(lr,p,type);
}
else
{
update(rr,p,type);
}
pushup(root);
}
int query(int root,int l,int r)
{
if(l<=tree[root].l&&tree[root].r<=r)
{
return tree[root].w;
}
int ans=0;
if(l<=mid)ans += query(lr,l,r);
if(r>mid)ans += query(rr,l,r);
return ans;
}
int way(int u,int v)///记录u,v的最短路,且重链最大
{
int ans=0;
while(top[u]!= top[v])
{
int tp1=top[u];
int tp2=top[v];
if(dep[tp1]<dep[tp2])
{
swap(tp1,tp2);
swap(u,v);
}
int tmp = query(1,dfn[tp1],dfn[u]);
if(tmp<dfn[u]-dfn[v]+1)return -1;
///如果路径长度是小于重链的长度,说明 里面肯定有白边 不合法
ans+=tmp;
u=fa[tp1];
tp1=top[u];
}
if(u==v)return ans;
if(dep[u]>dep[v])
{
swap(u,v);
}
int tmp = query( 1,dfn[ son[u] ],dfn[v] );
if(tmp<dfn[v]-dfn[u])return -1;
ans += tmp;
return ans;
}
struct E
{
int x;
int y;
}path[maxn];
int main()
{
memset(head,-1,sizeof(head));
int n;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
scanf("%d %d",&path[i].x,&path[i].y);
add(path[i].x,path[i].y);
add(path[i].y,path[i].x);
}
int root=1;
dfs1(root,0,1);
///树的根,该结点的父亲,该结点目前的深度
///dfs2(root,root);
for(int i=1;i<n;i++)
{
if(dfn[ path[i].x ]<dfn[ path[i].y ])
{
swap(path[i].x,path[i].y);
}
}
/*build(1,1,n);
int q;
scanf("%d",&q);
while(q--)
{
int ask,u,v;
scanf("%d %d %d",&ask,&u);
if(ask==1)
{
update(1,dfn[ path[u].x ],1);
}
else if(ask==2)
{
update(1,dfn[ path[u].x ],0);
}
else
{
scanf("%d",&v);
printf("%d\n",way(u,v));
}
}
printf("**");
}*/
dp[i][j]=dp[i][j]a[i][j].yd+a[i][j].ydxdp[i+1][j]+a[i][j].ydy*dp[i][j+1];
dp表示的是到达i,j点消耗的魔法值
求数学期望(概率dp)
#include<bits/stdc++.h>
using namespace std;
#define bug(x) cout<<#x<<"=="<<x<<endl;
const int maxn=1e5+10;
int a[maxn] = { 0 };
double dp[maxn] = { 0 };///记录概率
double now=1.0/6.0;
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
if(n==0&&m==0)break;
memset(a,-1,sizeof(a));
for(int i=1; i<=m; i++)
{
int u,v;
scanf("%d %d",&u,&v);
a[u] = v;
}
memset(dp,0,sizeof(dp));
for(int i=n-1;i>=0;i--)
{
if(~a[i])
{
dp[i]=dp[ a[i] ];
}
else
{
for(int j=1;j<=6;j++)
{
if(i+j>=n)
{
dp[i]+=now*dp[n];
}
else
{
dp[i]+=now*dp[i+j];
}
}
dp[i]++;
}
}
printf("%.4f\n",dp[0]);
}
}
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+10;
#define bug(x) cout<<#x<<"=="<<x<<endl;
double dp[1005]={0};
///i表示当前获奖的概率为 (0/1*i) %
int main()
{
int T;
scanf("%d",&T);
int cas=0;
while(T--)
{
double p;
scanf("%lf",&p);
memset(dp,0,sizeof(dp));
p/=100;
double hope = 1/p;
dp[1000]=hope;///这是肯定会得奖的临界情况
///bug(hope);
for(int i=999;i>=20;i--)
{
dp[i] += p*( (i/1000.0));
///第一种情况->直接得到
dp[i] += p*(1.0-i/1000.0)*(1+dp[min(1000,i+20)]);
///第二种情况,比赛赢了但是没有抽到,转移到dp[i+20]的情况,
///而且注意+(1-i/1000)因为需要一盘转移到下一个情况
dp[i] += (1-p)*(1+dp[min(1000,i+15)]);
///第三情况输了,转移到dp[i+15]的情况
}
cas++;
printf("Case %d: %.10f\n",cas,dp[20]);
}
/*
cin>>a;
int len = a.length();
int t;
scanf("%d",&t);
bug(t);
a=' '+a;
while(t--)
{
cin>>b;
int blen=b.length();
b=' '+b;
ll ans=0;
for(int i=1;i<=len;i++)
{
dp[i][0]=1;
for(int j=1;j<=blen;j++)
{
dp[i][j]=dp[i-1][j];
if(a[i]==b[j])
{
dp[i][j]=max(dp[i][j],dp[i-1][j-1]);
}
if(a[i]=='?')
{
dp[i][j]=max(dp[i-1][j-1],dp[i][j]);
}
if(a[i]=='?'&&j==1)
{
dp[i][j]=max(1,dp[i][j]);
}
if(j==blen)
{
ans += dp[i][j];
}
}
}
printf("%lld\n",ans);
}
*/
}
求概率
1
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e3+10;
#define bug(x) cout<<#x<<"=="<<x<<endl;
double dp[1005][1005] = { 0 };
int main()
{
int w,b;
scanf("%d %d",&w,&b);
for(int i=1;i<=1005;i++)dp[i][0]=1;
for(int i=1;i<=w;i++)
{
for(int j=1;j<=b;j++)
{
dp[i][j] += (i*1.0/(i+j));
double gl1=(j*1.0)/(i+j);
double gl2=((j-1)*1.0)/(i+j-1);
if(j>=3)
{
dp[i][j]+=gl1*gl2*(j-2)*1.0/(i+j-2)*dp[i][j-3];
}
if(i>=2)
{
dp[i][j]+=gl1*gl2*i*1.0/(i+j-2)*dp[i-1][j-2];
}
}
}
printf("%.9f\n",dp[w][b]);
}