zoukankan      html  css  js  c++  java
  • bzoj 3029 守卫者的挑战——概率期望dp+状态数思考

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3029

    先随便写了个dfs,记录“前 i 次、成功 j 次、容量-残片=k”的概率。因为是否可行只和“成功次数”还有“容量-残片个数”有关,和容量、残片具体数量无关。准备记忆化,但发现状态存不下。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define db double
    using namespace std;
    const int N=205,M=202005;
    int n,l,K,a[N];
    db p[N],ans;
    void dfs(int i,int j,int c,double w)//至少有c个 
    {
        if(c>n)c=n;
        if(i>n)
        {
            if(j>=l&&c>=0)ans+=w;return;
        }
        if(j+(n-i+1)<l)return;
        if(a[i]>=0)
        {
            dfs(i+1,j+1,c+a[i],w*p[i]);
            dfs(i+1,j,c,w*(1-p[i]));
        }
        else
        {
            dfs(i+1,j+1,c-1,w*p[i]);
            dfs(i+1,j,c,w*(1-p[i]));
        }
    }
    int main()
    {
        scanf("%d%d%d",&n,&l,&K);int x;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);p[i]=(db)x/100;
        }
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        dfs(1,0,K,1);
        printf("%.6lf
    ",ans);
        return 0;
    }
    View Code

    然后想到了 bzoj4247 挂饰 的思路。就是发现“容量-残片数量”大于n的话多出来的部分没什么用,可以把大于n记成等于n。这样第三维就只有2*n啦!然后就可以刷表了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define db double
    using namespace std;
    const int N=205,M=202005;
    int n,l,K,a[N];
    db p[N],ans,dp[2][N][N<<1];
    int main()
    {
        scanf("%d%d%d",&n,&l,&K);int x;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);p[i]=(db)x/100;
        }
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        dp[0][0][min(n,K)+N]=1;
        for(int i=0;i<n;i++)
        {
            int d=(i&1);
            for(int j=0;j<i;j++)
                for(int k=-n;k<=n;k++)dp[!d][j][k+N]=0;
            for(int j=0;j<=i;j++)
                for(int k=-n;k<=n;k++)
                {
                    if(a[i+1]>=0)
                    {
                        dp[!d][j+1][min(n,k+a[i+1])+N]+=dp[d][j][k+N]*p[i+1];//+=
                        dp[!d][j][k+N]+=dp[d][j][k+N]*(1-p[i+1]);
                    }
                    else
                    {
                        dp[!d][j+1][k-1+N]+=dp[d][j][k+N]*p[i+1];
                        dp[!d][j][k+N]+=dp[d][j][k+N]*(1-p[i+1]);
                    }
                }
        }
        int d=(n&1);
        for(int j=l;j<=n;j++)
            for(int k=0;k<=n;k++)
                ans+=dp[d][j][k+N];
        printf("%.6lf
    ",ans);
        return 0;
    }
  • 相关阅读:
    点双连通分量
    CF 839 E-最大团
    线性基
    CF 859 E
    【bzoj1303】[CQOI2009]中位数图
    【bzoj2282】[Sdoi2011]消防
    【bzoj2654]】tree
    【bzoj2600】 [Ioi2011]ricehub
    【bzoj4027】 [HEOI2015]兔子与樱花
    【bzoj3670】 [Noi2014]动物园
  • 原文地址:https://www.cnblogs.com/Narh/p/9362911.html
Copyright © 2011-2022 走看看