hdu-3366 Passage 概率DP 读懂就能AC hhh
http://acm.split.hdu.edu.cn/showproblem.php?pid=3366
读题的时候没发现这个P Q 1-P-Q是全集的划分,以为是独立事件,写错了转移方程233
先贪心得排个序,排序规则我们可以通过假设A B/B A这两种顺序,然后推导概率和的大小关系来得出。
然后分别讨论直接通过,免费到下一门,付费到下一门。
dp[i][j]存到达i门消费j的概率,dp[0][0]是初始状态,所以必命中,置为1,其他的概率需要推导得出,所以先置0。
#include <iostream> #include <string> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> #include <set> #include <queue> #define LL long long using namespace std; const LL N = 10005,M=15; int n, m; double dp[M][N]; struct node { double p, q; }r[N]; bool cmp(node a, node b) { return a.p*b.q > b.p*a.q;//推导概率公式 } int main(int argc, const char * argv[]) { //cin.sync_with_stdio(false); int t; //cin >> t; int cas = 1; scanf("%d", &t); while (t--) { //cin >> n >> m; scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) { scanf("%lf%lf", &r[i].p, &r[i].q); //cin >> r[i].p >> r[i].q; } sort(r, r + n, cmp); for (int i = 0; i <= m; i++)fill(dp[i], dp[i] + N, 0); double ans = 0; dp[0][0] = 1; for (int i = 0; i <= m; i++) { for (int j = 0; j < n; j++) { dp[i][j + 1] += dp[i][j]*(1.0 - r[j].p - r[j].q); dp[i + 1][j + 1] +=dp[i][j]*r[j].q; dp[i][j] *= r[j].p; ans += dp[i][j]; } } printf("Case %d: %.5f\n",cas++, ans); //cout << ans << endl; } return 0; }