首页 > 其他 > 详细

牛客练习赛 B题 烟花【DP】(经典)

时间:2018-09-08 11:05:40      阅读:206      评论:0      收藏:0      [点我收藏+]

<题目链接>

题目描述 

小a有技术分享图片个烟花,每个烟花代表着互不相同的颜色,对于第技术分享图片个烟花,它有技术分享图片的概率点燃,现在小a要去点燃它们,他想知道产生颜色的期望个数 及 产生恰好产生技术分享图片种颜色的概率

输入描述:

第一行两个整数技术分享图片接下来一行技术分享图片个数,第技术分享图片个数技术分享图片表示第技术分享图片个烟花被点燃的概率。

输出描述:

输出有两行,第一行表示产生不同颜色的期望个数,第二行表示产生恰好技术分享图片种颜色的概率,以换行符分割

输入

3 2
0.5 0.25 0.75

输出

1.5000
0.4062

说明

第二问样例解释:
技术分享图片
技术分享图片
技术分享图片

相加得
技术分享图片

备注:

对于
技术分享图片
的数据:
技术分享图片

对于
技术分享图片
的数据:
技术分享图片
输出均保留4位小数,若你的答案误差与std不超过技术分享图片即为正确

解题分析:
本题是比较经典的dp,dp[i][j]表示前i件物品中产生j件物品的概率,不难想到,状态转移方程为:dp[i][j] = dp[i-1][j]*(1-p[i])+dp[i-1][j-1]*p[i];
意思是:前i件物品中产生j个颜色的概率为前(i-1)个物品产生j个颜色*第i个物品不产生颜色的概率,加上前(i-1)件物品产生(j-1)种颜色*第i个物品产生颜色的概率。然后再用滚动数组优化成一维dp即可。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
double p[N];
double dp[1010];    //实际上是dp[i][j],只不过下面用了滚动数组,意义是前i个物品产生j中颜色的概率

int main(){
    int n,k;
    scanf("%d %d",&n, &k);
    double ans = 0;
    for(int i = 1; i <= n; i ++) scanf("%lf",&p[i]), ans += p[i];
    
    dp[0] = 1;
    for(int i = 1; i <= n; i ++){
        for(int j = k;j>=0;j--){
            dp[j] = dp[j]*(1-p[i])+dp[j-1]*p[i];
        }//前i个物品产生j种颜色的概率为,前i-1个物品产生 j种颜色的概率*第i个物品不产生颜色的概率加上前i-1个物品产生j-1个颜色的概率*第j个物品产生颜色的概率 
    }

    printf("%.4f\n%.4lf",ans,dp[k]);
    return 0;
}


2018-09-08

牛客练习赛 B题 烟花【DP】(经典)

原文:https://www.cnblogs.com/00isok/p/9608211.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!