zoukankan      html  css  js  c++  java
  • 概率DP

    POJ 3744 Scout YYF I

    这就是一个乱搞题,暴力发现TLE了,然后看了看discuss里说可以矩阵加速,想了一会才想明白怎么用矩阵,分着算的啊。先算f[num[i]-1]之类的,代码太长了,还是找找规律吧。。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <vector>
    #include <string>
    #include <queue>
    using namespace std;
    #define eps 1e-8
    int num[11];
    int judge(double x,double y)
    {
        double t = x-y;
        if(t < 0)
        t = -t;
        if(t < eps)
        return 1;
        else
        return 0;
    }
    int main()
    {
        int i,j,n,maxz;
        double p,f1,f2;
        while(scanf("%d%lf",&n,&p)!=EOF)
        {
            maxz = 0;
            for(i = 0; i < n; i ++)
            {
                scanf("%d",&num[i]);
                maxz = max(num[i],maxz);
            }
            sort(num,num+n);
            if(num[0] == 1)
            {
                printf("0.0000000
    ");
            }
            else
            {
                f2 = 1;
                f1 = 0;
                for(i = 2; i <= maxz+1; i ++)
                {
                    double t;
                    for(j = 0;j < n;j ++)
                    {
                        if(num[j] == i)
                        break;
                    }
                    if(j != n)
                    {
                        swap(f2,f1);
                        f2 = 0;
                    }
                    else
                    {
                        t = f2;
                        f2 = f2*p + f1*(1-p);
                        f1 = t;
                    }
                    if(judge(f1,f2))
                    {
                        for(j = 0;j < n;j ++)
                        {
                            if(num[j] > i)
                            {
                                i = num[j]-1;
                                break;
                            }
                        }
                    }
                }
                printf("%.7lf
    ",f2);
            }
        }
        return 0;
    }
    View Code

     CodeForces 148D Bag of mice

    乱推推,题意看清楚。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define eps 1e-8
    double dp[1001][1001];
    int in[1001][1001];
    double dfs(int w,int b)
    {
        double t;
        if(in[w][b])
        return dp[w][b];
        if(w == 0)
        return 0;
        t = w*1.0/(w+b);
        in[w][b] = 1;
        if(b >= 2)
        {
            if(b-2 > 0)
            return dp[w][b] = t + b*1.0/(w+b)*(b-1)/(w+b-1)*(b-2)/(w+b-2)*dfs(w,b-3) + b*1.0/(w+b)*(b-1)/(w+b-1)*w/(w+b-2)*dfs(w-1,b-2);
            else
            return dp[w][b] = t + b*1.0/(w+b)*(b-1)/(w+b-1)*w/(w+b-2)*dfs(w-1,b-2);
        }
        return dp[w][b] = t;
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        printf("%.9lf
    ",dfs(n,m));
        return 0;
    }
    View Code

     HDU 3853   LOOPS

    入门题。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <vector>
    #include <string>
    #include <queue>
    using namespace std;
    #define eps 1e-6
    double dp[1001][1001];
    double w[1001][1001][3];
    int judge(double x)
    {
        if(x < 0)
        x = -x;
        if(x < eps)
        return 1;
        else
        return 0;
    }
    int main()
    {
        int m,n,i,j,k;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(i = 0;i < n;i ++)
            {
                for(j = 0;j < m;j ++)
                {
                    for(k = 0;k < 3;k ++)
                    scanf("%lf",&w[i][j][k]);
                }
            }
            dp[n-1][m-1] = 0;
            for(i = n-1;i >= 0;i --)
            {
                for(j = m-1;j >= 0;j --)
                {
                    if(i == n-1&&j == m-1) continue;
                    if(judge(w[i][j][0]-1)) continue;
                    dp[i][j] = (dp[i][j+1]*w[i][j][1] + dp[i+1][j]*w[i][j][2] + 2)/(1-w[i][j][0]);
                }
            }
            printf("%.3lf
    ",dp[0][0]);
        }
        return 0;
    }
    View Code

     ZOJ 3640 Help Me Escape

    硬做就行,取整符号,你认识吗...

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    using namespace std;
    #define eps 1e-8
    double dp[20001];
    int in[20001];
    int c[101];
    int n;
    double dfs(int x)
    {
        int i;
        if(in[x])
        return dp[x];
        double ans,t2;
        t2 = ((sqrt(5.0)+1))*0.5;
        ans = 0;
        for(i = 0;i < n;i ++)
        {
            if(x > c[i])
            ans += (int)(t2*c[i]*c[i]);
            else
            ans += dfs(x+c[i])+1;
        }
        ans /= n;
        in[x] = 1;
        return dp[x] = ans;
    }
    int main()
    {
        int i,f;
        while(scanf("%d%d",&n,&f)!=EOF)
        {
            memset(in,0,sizeof(in));
            for(i = 0;i < n;i ++)
            scanf("%d",&c[i]);
            printf("%.3lf
    ",dfs(f));
        }
        return 0;
    }
    View Code

    ZOJ 3380 Patchouli's Spell Cards

    这个题,完全就是组合DP的感觉。

    题意要求至少有l个,求反面,所有的数字都是0-l-1就行了。

    dp[i][j] 前j种,放了i个位置,枚举当前颜色,放0到l-1种,这个问题就是m个位置,插入n个相同的数,以前做过,把n插板,然后从m+1个空里选。

    用java第一次TLE了,记忆化了一下fun函数,就过了。

    import java.math.BigInteger;
    import java.util.Scanner;
    
    public class Main {
        static BigInteger c[][] = new BigInteger[101][101];
        static BigInteger s[][] = new BigInteger[110][110];
        static boolean in[][] = new boolean[110][110];
        public static BigInteger gcd(BigInteger a, BigInteger b) {
            if (b.compareTo(BigInteger.valueOf(0)) == 0)
                return a;
            else
                return gcd(b, a.mod(b));
        }
    
        public static BigInteger fun(int n, int m) {
            int minz, i;
            if(in[n][m])
                return s[n][m];
            if (n == 0 || m == 0)
                return BigInteger.valueOf(1);
            if (n < m + 1)
                minz = n;
            else
                minz = m + 1;
            BigInteger ans = BigInteger.valueOf(0);
            for (i = 1; i <= minz; i++) {
                ans = ans.add(c[m + 1][i].multiply(c[n - 1][i - 1]));
            }
            in[n][m] = true;
            return s[n][m] = ans;
        }
    
        public static void main(String args[]) {
            Scanner cin = new Scanner(System.in);
            BigInteger dp[][] = new BigInteger[101][101];
            int i, j, k, n, m, l;
            for (i = 0; i <= 100; i++) {
                for (j = 0; j <= 100; j++)
                    c[i][j] = BigInteger.valueOf(0);
            }
            for (i = 0; i <= 100; i++)
                c[i][0] = BigInteger.valueOf(1);
    
            for (i = 1; i <= 100; i++) {
                for (j = 1; j <= 100; j++)
                    c[i][j] = c[i - 1][j - 1].add(c[i - 1][j]);
            }
            while (cin.hasNext()) {
                m = cin.nextInt();
                n = cin.nextInt();
                l = cin.nextInt();
                if (l > m) {
                    System.out.println("mukyu~");
                    continue;
                }
                for (i = 0; i <= m; i++) {
                    for (j = 0; j <= n; j++)
                        dp[i][j] = BigInteger.valueOf(0);
                }
                dp[0][0] = BigInteger.valueOf(1);
                for (i = 0; i < m; i++) {
                    for (j = 0; j < n; j++) {
                        for (k = 0; k < l; k++) {
                            if (dp[i][j].compareTo(BigInteger.valueOf(0)) == 0)
                                continue;
                            if (i + k > m)
                                continue;
                            dp[i + k][j + 1] = dp[i + k][j + 1].add(dp[i][j]
                                    .multiply(fun(i, k)));
                        }
                    }
                }
                BigInteger ans = BigInteger.valueOf(n).pow(m);
                BigInteger res = BigInteger.valueOf(0);
                for (i = 1; i <= n; i++) {
                    res = res.add(dp[m][i]);
                }
                BigInteger t = gcd(ans.subtract(res), ans);
                System.out.println(ans.subtract(res).divide(t) + "/"
                        + ans.divide(t));
            }
    
        }
    }
    View Code

     SGU 495 Kids and Prizes

    感觉是神题呢,这是咋推的,我想了半天,硬做来了个二维的...看别人的题解,直接一位搞定。。。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    using namespace std;
    int n,num;
    double dp[100010];
    double dfs(int step,int m)
    {
    
        double ans;
        if(step == n)
        {
            return (m*1.0/num);
        }
        ans = (m*1.0/num)*(dfs(step+1,m-1) + 1);
        if(m != num)
        ans += (num-m)*1.0/num*dfs(step+1,m);
        return ans;
    }
    int main()
    {
        int m,i;
    //    while(scanf("%d%d",&m,&n)!=EOF)
    //    {
    //        num = m;
    //        printf("%.9lf
    ",dfs(1,m));
    //    }
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            dp[1] = 1;
            for(i = 2;i <= m;i ++)
            dp[i] = (1-dp[i-1])*dp[i-1] + dp[i-1]*(dp[i-1]-1.0/n);
            double ans = 0;
            for(i = 1;i <= m;i ++)
            ans += dp[i];
            printf("%.10lf
    ",ans);
        }
        return 0;
    }
    View Code

     ZOJ 3329 One Person Game

    跟省赛的题非常相似,所有的dp[i]都用o1[i]*dp[0]+o2[i]表示,最后就解出dp[0]来了。

    #include <cstdio>
    using namespace std;
    double o1[600];
    double o2[600];
    int main()
    {
        int n,k1,k2,k3,a,b,c,i,j,k,u,t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d%d%d%d%d",&n,&k1,&k2,&k3,&a,&b,&c);
            for(i = n;i >= 0;i --)
            {
                o1[i] = 1.0/k1/k2/k3;
                o2[i] = 1;
                for(j = 1;j <= k1;j ++)
                {
                    for(k = 1;k <= k2;k ++)
                    {
                        for(u = 1;u <= k3;u ++)
                        {
                            if(i+j+k+u > n) continue;
                            if(j == a&&k == b&&u == c) continue;
                            o1[i] += 1.0/k1/k2/k3*o1[i+j+k+u];
                            o2[i] += 1.0/k1/k2/k3*o2[i+j+k+u];
                        }
                    }
                }
            }
            printf("%.10lf
    ",o2[0]/(1.0-o1[0]));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    机械奥妙
    双向可控硅
    开关电源
    阻容降压电路
    手机充电电源的电路原理
    运算放大电路
    剃须刀电路
    d039: 点的位置
    d029: 求出2-100之间的所有质数(素数)
    d023: 各位数字之和
  • 原文地址:https://www.cnblogs.com/naix-x/p/3723552.html
Copyright © 2011-2022 走看看