hdu 3203 Door Repairing
对于一道门,n个人经过。每人有p的概率把门弄坏,修好门需要a元,若某人经过时门是坏的则罚b元。求期望的最小支出。
比较明显的概率dp题,关键是找出推导关系。本题中,如果所有人都通过了,那么门是好是坏也就不需要管了。有这个条件在,所以从后往前推导比较容易。
dp[n][0]表示第n个人经过时,门是坏的。dp[n][1]则表示门是好的。
dp[n][0] = min(dp[n+1][0]+b, a+p*dp[n+1][0]+(1.0-p)*dp[n+1][1]);
dp[n][1] = p*dp[n+1][0]+(1.0-p)*dp[n+1][1];
#include <stdio.h> #include <vector> #include <string> #include <algorithm> #include <queue> #include <cstring> #include <map> #include <set> #include <iostream> #include <cmath> using namespace std; // http://acm.hdu.edu.cn/showproblem.php?pid=3203 #ifdef __GNUC__ typedef long long LL; inline void opt64(LL a) { printf("%lld", a); } #else typedef __int64 LL; inline void opt64(LL a) { printf("%I64d", a); } #endif const int MAXN = 100005; // 逆向推导 int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int n; double a, p, b; double f0, f1, p0, p1; while (scanf("%d%lf%lf%lf", &n, &p, &a, &b)) { if (n==0 && a==0 && p==0 && b==0) break; p /= 100.0; f0 = min(a, b); f1 = 0.0; for (int i = 1; i< n; ++i) { p0 = min(f0+b, a+p*f0+(1.0-p)*f1); p1 = p*f0+(1.0-p)*f1; f0 = p0; f1 = p1; } printf("%.4lf\n", f1); } return 0; }