标签:
题目链接:http://codeforces.com/problemset/problem/442/B
题目大意:有n个人,第i个人出一道题的概率是pi,现在选出一个子集,使得这些人恰好出一个题的概率最大。问最大概率。
可以仿照背包问题来做,即每个人可问可不问。
f[i][j]代表从前i个人里问j个人所获得1个题的最大概率。
f[i][j] = max{ f[i-1][j], f[i-1][j-1]*(1-p[i])+z[i-1][j-1]*p[i] };
z[i][j]为从前i个人里问j个人所获得1个题的最大概率对应的一个题也出不出来的概率。
转移见代码
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <map> 6 #include <set> 7 #include <bitset> 8 #include <cmath> 9 #include <numeric> 10 #include <iterator> 11 #include <iostream> 12 #include <cstdlib> 13 #include <functional> 14 #include <queue> 15 #include <stack> 16 #include <string> 17 #include <cctype> 18 using namespace std; 19 #define PB push_back 20 #define MP make_pair 21 #define SZ size() 22 #define ST begin() 23 #define ED end() 24 #define CLR clear() 25 #define ZERO(x) memset((x),0,sizeof(x)) 26 typedef long long LL; 27 typedef unsigned long long ULL; 28 typedef pair<int,int> PII; 29 const double EPS = 1e-8; 30 31 int n; 32 double f[111][111],p[111],z[111][111]; 33 34 int main(){ 35 scanf("%d",&n); 36 for(int i=1;i<=n;i++) scanf("%lf",&p[i]); 37 for(int i=0;i<111;i++) z[0][i] = z[i][0] = 1.0; 38 for(int i=1;i<=n;i++){ 39 for(int j=1;j<=i;j++){ 40 // printf("i=%d,j=%d\n",i,j); 41 // printf("f[i-1][j]=%f,f[i-1][j-1]*(1-p[i])+z[i-1][j-1]*p[i]=%f\n",f[i-1][j],f[i-1][j-1]*(1-p[i])+z[i-1][j-1]*p[i]); 42 if( f[i-1][j]<f[i-1][j-1]*(1-p[i])+z[i-1][j-1]*p[i] ){ 43 f[i][j] = f[i-1][j-1]*(1-p[i])+z[i-1][j-1]*p[i]; 44 z[i][j] = z[i-1][j-1]*(1-p[i]); 45 } else { 46 f[i][j] = f[i-1][j]; 47 z[i][j] = z[i-1][j]; 48 } 49 } 50 } 51 double ans = 0; 52 for(int i=1;i<=n;i++){ 53 ans = max(ans,f[n][i]); 54 } 55 printf("%.12f\n",ans); 56 return 0; 57 }
[CF442B] Andrey and Problem (概率dp)
标签:
原文地址:http://www.cnblogs.com/llkpersonal/p/4541330.html