zoukankan      html  css  js  c++  java
  • HGOI 20181027 幻象(概率DP)

    • 40 pts: 考场上打了40分暴力,理论的话就是概率树,把每一个状态去去到各个带权(概率)的和就是答案

    最终处理的话就是dfs出01序列0代表没有幻象,1代表出现幻象然后在每一次dfs出一段序列的时候双指针check一下更新答案

    代码并不难,就是这样写的复杂度O(2n

    code: (40pts

    # include <bits/stdc++.h>
    using namespace std;
    double ans;
    int n,a[105];
    double p1[105],p0[105];
    void get()
    {
        double pr=1.0;
        for (int i=1;i<=n;i++)
         if (a[i]==1) pr*=p1[i];
         else pr*=p0[i];
        int i=1; double sum=0;
        while (i<=n) {
            if (a[i]==0) { i++; continue;}
            int j=i; int res=0; 
            while (a[j]==1&&j<=n) j++,res++;
            i=j;
            sum=sum+(double) res*res;
        } 
        ans+=sum*pr;
    }
    void dfs(int dep)
    {
        if (dep==n+1) { get(); return; }
        a[dep]=1; dfs(dep+1);
        a[dep]=0; dfs(dep+1);
    }
    int main()
    {
        freopen("phantom.in","r",stdin);
        freopen("phantom.out","w",stdout);
        scanf("%d",&n);
        int x;
        for (int i=1;i<=n;i++) {
            scanf("%d",&x);
            p1[i]=(double) x/100.0;
            p0[i]=1.0-p1[i];
        }
        dfs(1);
        printf("%.1lf
    ",ans);
        return 0;
    }
    • 60pts:hjc20032003考场上写了60分DP,这大概是O(n2)[前缀积]或者是O(n3)复杂度

    具体做法是这样的:

    令f[i]表示第i秒前幻象的期望,枚举是从j转移过来的,(这里需要注意枚举的j是断点所以从0开始枚举表示不断,否则会重复计数)

    转移方程式这样的:

    code:(60pts)

    # include <bits/stdc++.h>
    using namespace std;
    const int MAXN=105;
    double f[MAXN],p[MAXN];
    int n;
    int main()
    {
        scanf("%d",&n); int x;
        for (int i=1;i<=n;i++) {
            scanf("%d",&x);
            p[i]=(double)x/100.0;
        } 
        f[1]=p[1];
        for (int i=2;i<=n;i++) {
            f[i]=0.0;
            for (int j=0;j<=i;j++) {
                double pr=1.0;
                for (int k=j+1;k<=i;k++) pr*=p[k];
                f[i]+=pr*(1-p[j])*(f[j-1]+(i-j)*(i-j));
            }
        }
        printf("%.1lf
    ",f[n]);
        return 0;
     }
    • 100pts: 状态改变一下,

    记f[i]为第i秒之前期望幻象值

    记g[i]为第i秒前连续期望幻象值

    显然

      • g[i]=(g[i-1]+1)*P[i]
      • f[i]=f[i-1]+P[i]*((g[i-1]+1)2-g[i-1]2)

    于是完成了O(1)转移,总复杂度O(n)

    code(100 pts) 

    # include <bits/stdc++.h>
    using namespace std;
    const int MAXN=1e6+10;
    double p[MAXN],f[MAXN],g[MAXN];
    int n;
    double sqr(double x){ return x*x;}
    int main()
    {
        scanf("%d",&n);
        int x;
        for (int i=1;i<=n;i++) {
            scanf("%d",&x);
            p[i]=(double) x/100.0;
        }
        f[1]=p[1]; g[1]=p[1];
        for (int i=2;i<=n;i++) {
            f[i]=f[i-1]+p[i]*(sqr(g[i-1]+1)-sqr(g[i-1]));
            g[i]=(g[i-1]+1)*p[i];
        } 
        printf("%.1lf
    ",f[n]);
        return 0;
    }

     

  • 相关阅读:
    luogu P3801 红色的幻想乡
    [USACO07OPEN]吃饭Dining
    [SCOI2007]蜥蜴
    [SDOI2011]染色
    [USACO07DEC]Sightseeing Cows
    [HNOI2007]紧急疏散EVACUATE
    [ZJOI2009]假期的宿舍
    [SDOI2013]费用流
    [CQOI2009]跳舞
    使用chrony安装chrony
  • 原文地址:https://www.cnblogs.com/ljc20020730/p/9862172.html
Copyright © 2011-2022 走看看