HDU 3366 Passage (dp)



题意:n条通道和m百万元,每一条通道有三种情况,一是直接出去,概率是p,二是碰上士兵,给1百万块再回去,概率是q,或者是死路,概率是1-p-q。问最终出去时最优可能性。

思路:概率dp,既然问最优可能性,肯定是最有可能跑出去的情况最好了,就算跑不出去也要少碰士兵,所以先按p/q从大到小排序,然后dp[i][j]代表在第i个通道,还有j万元的时候能出去的概率。

能直接出去的话,最终结果加上dp[i][j]*p;如果碰上士兵就dp[i+1][j-1]+=dp[i][j]*q;如果是死路,就dp[i+1][j]+=dp[i][j]*(1-p-q);

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CPY(A, B) memcpy(A, B, sizeof(A))
typedef long long LL;
typedef unsigned long long uLL;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-9;
const double OO = 1e20;
const double PI = acos (-1.0);
int dx[]= {0,1,1,1,0,-1,-1,-1};
int dy[]= {1,1,0,-1,-1,-1,0,1};
int gcd (const LL &a, const LL &b) {return b==0?a:gcd (b,a%b);}
using namespace std;
double dp[1010][11];//小心double
struct node {
    double p,q;
    bool operator < (const node &a) const {
        return p/q>a.p/a.q;
    }
} num[1010];
int main() {
    int T,cas=1; scanf ("%d",&T);
    while (T--) {
        int n,m; scanf ("%d%d",&n,&m);
        for (int i = 0; i < n; i++) {
            scanf ("%lf%lf",&num[i].p,&num[i].q);
        }
        sort (num,num+n);
        double ans=0.0;
        memset (dp,0,sizeof (dp) );
        dp[0][m]=1.0;
        for (int i=0; i=0; j--) {
                ans+=num[i].p*dp[i][j];
                if (j>=1) {dp[i+1][j-1]+=dp[i][j]*num[i].q;}
                dp[i+1][j]+=dp[i][j]* (1-num[i].q-num[i].p);
            }
        }
        printf ("Case %d: %.5f\n",cas++,ans);
    }
    return 0;
}


你可能感兴趣的:(HDU,动态规划-概率dp)