期望dp 入入门

poj 炸了….过个把星期才能好…先刷一下HDU上的题

期望dp
这一类题,简单的说就是求期望。
一般都是从后往前推,因为最后的状态和值我们知道…
通过例题来了解~
LOOPS HDU - 3853

题意:求从(1,1)走到(r,c)的期望,每个位置有三个选择,原地不动,向右走,向下走,概率分别是(c1,c2,c3)。

分析:
dp[r][c]=0;
dp[i][j]=c1*dp[i][j]+c2*dp[i][j+1]+c3*dp[i+1][j]
递推是由已知推未知,右边的dp[i][j]未知,转移到左边
dp[i][j]=(c2*dp[i][j+1]+c3*dp[i+1][j])/(1-c1);
然后从后往前推就行了,这里注意分母不能是0,特判一下1-c1为0的情况

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 1e3+10;
double c1[maxn][maxn],c2[maxn][maxn],c3[maxn][maxn],dp[maxn][maxn];
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",&c1[i][j],&c2[i][j],&c3[i][j]);
        for(int i=0;i<=1000;i++)
            for(int j=0;j<=1000;j++) dp[i][j]=0;
        for(int i=r;i>=1;i--)
            for(int j=c;j>=1;j--){
                if(i==r&&j==c) continue;
                if(abs(1.0-c1[i][j])<=1e-3) {dp[i][j]=2;continue;}
                dp[i][j]=(c2[i][j]*dp[i][j+1]+c3[i][j]*dp[i+1][j]+2)/(1.0-c1[i][j]);
            }
        printf("%.3f\n",dp[1][1]);
    }
    return 0;
}

Aeroplane chess HDU - 4405

题意:一种游戏,在一维坐标中,从0点出发,每次都会摇股子,有1,2,3,4,5,6这几种,摇到哪个就前进几个整点,比如x点,摇到了2点,就到了x+2点上。
其中还有几个飞行航线,比如(x,y)意思就是在x点可以直接跳到y点,不用摇股子。到n点,或者大于n点就算赢,问赢的期望。

分析:和大富翁游戏是不是有点像~
如果没有飞行航线的话,那么就和上面题目一样了,状态方程为:
dp[i]=(1.0/6.0)*(dp[i+1]+dp[i+2]+dp[i+3]+dp[i+4]+dp[i+5]+dp[i+6])+1.0;

这个飞行航线,只用将dp[x]=dp[y]就行了~

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <vector>

using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 1e5+10;
double dp[maxn];
int vis[maxn];
vector<int> v[maxn];
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF&&(n+m))
    {
        for(int i=0;i<=100007;i++) {dp[i]=0;vis[i]=0;}
        for(int i=0;i<=n;i++) v[i].clear();
        for(int i=0;i<m;i++)
        {
            int x,y;
            scanf("%d %d",&x,&y);
            v[y].push_back(x);
        }
        for(int j=0;j<v[n].size();j++){//因为可能直接跳到n点的
                dp[v[n][j]]=dp[n];
                vis[v[n][j]]=1;
        }
        for(int i=n-1;i>=0;i--)
        {
            if(!vis[i])
            dp[i]=(1.0/6.0)*(dp[i+1]+dp[i+2]+dp[i+3]+dp[i+4]+dp[i+5]+dp[i+6])+1.0;
            for(int j=0;j<v[i].size();j++){
                dp[v[i][j]]=dp[i];
                vis[v[i][j]]=1;
            }
            vis[i]=1;
        }
        printf("%.4f\n",dp[0]);
    }
    return 0;
}

codeforces 867D
这个期望dp还是没有想明白……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值