Passage(HDU3366)

题意

有一个百万富翁被困在城堡里,有n个走廊通向外面。这n个走廊有两个属性值p[i],q[i] 分别表示在这条走廊成功走出去的几率和遇见士兵的几率,如果遇见士兵的话,就需要给他1万元,然后返回承包,还有(1-p[i]-q[i])的几率走廊是个死胡同,不能出去,然后就会走回城堡。
现在已知这个百万富翁携带有m万元,求逃出的概率。

分析

首先发现这个富翁一定会贪心的走走廊。具体怎么贪心呢。就是走成功逃出几率大而且被抓概率小的走廊。成功脱出的概率是p/(p+q)化简一下去掉常数就是p/q 所以按这个东西排序即可。
然后是往DP上想。

状态的定义

dp[i][j]表示还剩下j万元,活着走出第i条走廊的概率。

答案是什么

i=0n1 j=0m (p[i+1]dp[i][j])

初始化

dp[0][0]=1.0 剩下的都赋值为0。

状态转移方程

对于任意一个状态[i,j],都会往三种状态转移
p[i+1]的概率逃出:res+=p[i+1]*dp[i][j]
q[i+1]的概率被抓:dp[i][j-1]+=q[i+1]*dp[i][j] {j>0}
1-p[i+1]-q[i+1]的概率什么都没发生,回来:dp[i+1][j]+=(1-p[i]-q[i])*dp[i][j]

code

#include
#include
#include
using namespace std;
void Max(double &x,double y){if (xstruct AC{double p,q;}a[1005];
double dp[1005][12];

bool cmp(AC a,AC b){return a.p*b.q>b.p*a.q;}

int main(){
    int t,n,m,i,j;
    scanf("%d",&t); int cnt=0;
    for (; t; t--){
        scanf("%d%d",&n,&m);
        for (i=1; i<=n; i++)scanf("%lf%lf",&a[i].p,&a[i].q);
        sort(a+1,a+n+1,cmp);
        double res=0;
        memset(dp,0,sizeof(dp)); dp[0][0]=1;
        for (i=1; i<=n; i++){
            for (j=0; j<=m; j++){
                res+=dp[i-1][j]*a[i].p;
                dp[i][j+1]+=dp[i-1][j]*a[i].q;
                dp[i][j]+=dp[i-1][j]*(1-a[i].q-a[i].p);             
            }           
        }       

        printf("Case %d: ",++cnt);
        printf("%.5f\n",res);   
    }   
    return 0;
}

反思

其实这个大概还是好想的,不过一开始写的时候没有想到贪心的走…然后卡了很久。非要说的话这题就是贪心+概率Dp这样的…?
大概还是要多分析分析题目….这样。

我太菜了….这里写图片描述

你可能感兴趣的:(DP,——概率DP,贪心)