1. 程式人生 > >投擲硬幣(動態規劃)

投擲硬幣(動態規劃)

#1506 : 投擲硬幣

時間限制:10000ms 單點時限:1000ms 記憶體限制:256MB

描述

小Hi有一枚神奇的硬幣。已知第i次投擲這枚硬幣時,正面向上的概率是Pi。  

現在小Hi想知道如果總共投擲N次,其中恰好M次正面向上的概率是多少。

輸入

第一行包含兩個整數N和M。

第二行包含N個實數P1, P2, ... PN。  

對於30%的資料,1 <= N <= 20  

對於100%的資料,1 <= N <= 1000, 0 <= M <= N, 0 <= Pi <= 1

輸出

輸出一行一個實數表示恰好M次正面向上的概率。注意行末需要包含一個換行符'\n'。  

輸出與標準答案誤差在0.001以內都被視為正確。

樣例輸入
2 1
0.5 0.5
樣例輸出
0.500000
AC code:
#include<iostream>
#include<stdio.h>
#include<map>
#include<vector>
#include<queue>
#include<set>
#include<cstdlib>
#include<string.h>
#include<algorithm>
#include<cmath>
#define MAXN 1000010
#define EPS 1e-9
using namespace std;

double pi[1010],dp[1001][1001];
int n,m; 

int main()
{
//	freopen("D:\\in.txt","r",stdin);
	int i,j;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		for(i=1;i<=n;i++)
		{
			scanf("%lf",&pi[i]);
		}
		memset(dp,0,sizeof(dp));
		dp[1][1]=pi[1];
		dp[1][0]=1-pi[1];
		for(i=2;i<=n;i++)
		{
			dp[i][0]=dp[i-1][0]*(1-pi[i]);
		}
		for(i=2;i<=n;i++)
		{
			for(j=1;j<=i;j++)
			{
				dp[i][j]=dp[i-1][j]*(1-pi[i])+dp[i-1][j-1]*pi[i];
			}
		}
		printf("%lf\n",dp[n][m]);
	}
	return 0;
}