zoukankan      html  css  js  c++  java
  • URAL 1776 Anniversary Firework (概率,区间DP)

    坑,一开始以为,分成两半的时候去最大那个就行了,

    实际上这样是不对的,因为有可能出现小的一半的时间比大的要长,

    因为还和等待次数有关,且转移的时候需要用到次数更小的状态,

    所以状态定义为二维,dp[i][j]表示长度为i的区间,放小于等于j次的概率。

    要求确切的某次的概率,比如k,就只要用dp[i][k]-dp[i][k-1]就行了。

    如何转移?从小到大枚举i,从小到大枚举j,初始化dp[i][j] = dp[i][j-1],

    然后求出确切等待j次的概率,以k为界限划分区间,分成l,r两段,加上l区间等待j-1次且r区间等待小于等于j-1次的概率,

    类似得加上r区间等待j-1次且l区间等带小于等于j-1次的概率,然后减掉重复计算的状态。

    因为只要求中间等待的次数,且一开始要放两个鞭炮,所以可以等效为一开始不计等待,之后每次都计算等待时间。

    还有一个细节是每次j从2开始枚举,放一次的只可能是长度为1的情况。

    g++使用%lf正常,但在有些oj却会出问题

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 402;
    
    double dp[maxn][maxn];
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int n; scanf("%d",&n);
        n -= 2;
    
        for(int i = 0; i <= n; i++){
            for(int j = i; j <=n; j++)
                 dp[i][j] = 1;
        }
    
        for(int i = 3; i <= n; i++){
            double e = 1./i;
            for(int j = 2; j < i; j++){
                dp[i][j] = dp[i][j-1];
                for(int k = 1; k <= i; k++){
                    int l = k-1,r = i-k;
                    double p1 = dp[l][j-1] - dp[l][j-2], p2 = dp[r][j-1] -  dp[r][j-2];
                    double p3 = dp[l][j-1];
                    double p4 = dp[r][j-1];
                    dp[i][j] += e*(p1*p4 + p2*p3 - p2*p1);
                }
            }
        }
        double ans = 0;
        for(int i = 1; i <= n; i++){
            ans += (dp[n][i]-dp[n][i-1])*i*10;
        }
        printf("%.11lf
    ",ans);
        return 0;
    }
  • 相关阅读:
    在Eclipse/STS里添加代码反编译器(.class)步骤
    关于页面添加字段
    关于jeesite Date和时间戳问题
    关于前端ajax通过实体类向后端传参报不存在问题
    引入字典
    关于添加主键
    简单的前后端分离项目 部署到 centos7
    Cenost7 Mysql5.7 安装 并打开远程访问
    npm install vue-cli -g 报错
    docker 笔记 docker 基础 docker 常用命令
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4728582.html
Copyright © 2011-2022 走看看