题意:n个盒子,第i个盒子有奖品的概率为a[i].问选若干个盒子后,正好获得一个奖品的概率最大是多少?
n<=100,0<=a[i]<=1.0
假如选的是子集s,一共k个物品.则正好中一个奖品的概率为 tot=(p1*q2*..qk)+(q1*p2*..qk)+...(q1*q2...pk).
现在设dp[i][j] 前i个物品选j个正好中一个奖品的最大概率.
dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]*q[i]+(q1*q2..q[k-1]*p[k])) dp[i-1][j-1]相当于选j-1个时的tot.
n<=100,0<=a[i]<=1.0
假如选的是子集s,一共k个物品.则正好中一个奖品的概率为 tot=(p1*q2*..qk)+(q1*p2*..qk)+...(q1*q2...pk).
现在设dp[i][j] 前i个物品选j个正好中一个奖品的最大概率.
dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]*q[i]+(q1*q2..q[k-1]*p[k])) dp[i-1][j-1]相当于选j-1个时的tot.
现在只要把[q[1]..q[j-1]]求出来即可.求方案也可以递推. 总共O(n^3).
正解是贪心:从概率大的往下选 若添加一下一个能使答案增加 则加入下一个.O(nlogn)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e2+5;
int n;
double p[N],q[N],dp[N][N];
vector<double> v[N][N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>p[i],q[i]=1-p[i];
dp[0][0]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
dp[i][j]=dp[i-1][j];
v[i][j]=v[i-1][j];
double res=1;
for(int k=0;k<v[i-1][j-1].size();k++)
res*=v[i-1][j-1][k];
res*=p[i];
if(dp[i][j]<dp[i-1][j-1]*q[i]+res)
{
dp[i][j]=dp[i-1][j-1]*q[i]+res;
v[i][j]=v[i-1][j-1];
v[i][j].push_back(q[i]);
}
}
}
double ans=0;
for(int i=1;i<=n;i++)
ans=max(dp[n][i],ans);
printf("%.10lf\n",ans);
return 0;
}