题意:T组测试数据,一个人困在了城堡中,有n个通道,m百万money ,每个通道能直接逃出去的概率为 P[i] ,遇到士兵的概率为 q[i],
遇到士兵得给1百万money,否则会被杀掉,还有 1-p[i]-q[i] 的概率走不通,要回头。问在可以选择的情况下,逃出去的概率是多少?
析:这个题很明显是概率DP么,就是不会。。。。在比赛时,读完题,直接放弃。。。。。
最后还是问的学长,是这样的,d[i][j],表示走第 i 个管道时,还剩 j 百万,那么怎么状态方程怎么转呢?
第一种情况:走了一个死胡同,走不通一,再走回来,那么d[i+1][j] = d[i][j] - (1-p[i]-q[i]);
第二种情况:碰到士兵了,交钱呗,d[i+1][j-1] = d[i][j] * q[i];
第三种情况:出去了,ans += d[i][j] * p[i];
那么剩下的就很简单了?no,如果这么写,第二组样例不过,因为有一个优先的问题,很明显是越早出去越好了,所以先要排个序,
规则是p/q大优先。现在剩下的就很简单了。
代码如下:
#include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <set> #include <queue> #include <string> #include <algorithm> #include <vector> #include <map> using namespace std ; typedef long long LL; const int maxn = 1e3 + 5; const int INF = 0x3f3f3f3f; struct node{ double p, q; bool operator < (const node &pq) const{ return p/q > pq.p/pq.q; } }; double d[maxn][12]; node a[maxn]; int main(){ int n, m, T; cin >> T; for(int kase = 1; kase <= T; ++kase){ cin >> n >> m; for(int i = 1; i <= n; ++i) cin >> a[i].p >> a[i].q; memset(d, 0, sizeof(d)); d[1][m] = 1; sort(a+1, a+n+1); double ans = 0; for(int i = 1; i <= n; ++i){ for(int j = m; j >= 0; --j){ d[i+1][j] += d[i][j] * (1-a[i].p-a[i].q); d[i+1][j-1] += d[i][j] * a[i].q; ans += d[i][j] * a[i].p; } } printf("Case %d: %.5lf ", kase, ans); } return 0; }