• POJ1322 Chocolate 动态规划


    这题当M=N=0的时候要输出1.000  刚写的时候默认从第二次开始取了.

    详见代码:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    /*
    题意:从一个拥有无限多的盒子中拿出不同颜色的糖果,拿出任何一种颜色的概率都是1/C
         每次拿出来的糖果都放在桌子上,如果有相同颜色的糖果,就把这两颗糖果吃掉.问
         拿了N次后,桌子上面剩余的糖果数量为M的概率是多大 
         
    解法:设状态dp[i][j]为选i次后剩余j颗糖果的概率为多大,省略了一维糖果的颜色数,因此
         每次需要重新计算这个dp值,有如下dp方程:
         dp[i][j] = dp[i-1][j-1] * (C-j+1)/C + dp[i-1][j+1] * (j+1)/C
         含义就是从上一次后拿到了一颗不同颜色的糖果,桌子上增加了一颗糖果而来
         或者是拿到了一颗相同颜色的糖果,桌子上减少了一颗糖果而来 
         
         通过牛人的测试,当N大于1000的时候,为偶数就当做1000处理,为奇数的时候就当做
         1001处理,因为N很大之后,仅仅靠小数点的后三位已经反映不去其差别 
    */
    
    int C, M, N; 
    double dp[2][1005][105]; 
    
    void DP() {
        memset(dp, 0, sizeof (dp)); 
        dp[1][1][1] = 1.0; // 摸一次一定会得到一个颜色的糖果
        for (int i = 2; i <= N; ++i) {
            int x = i & 1;
            for (int j = 0; j <= C; ++j) {
                if (j - 1 >= 0)
                    dp[x][i][j] += dp[!x][i-1][j-1]*(C-j+1)/C;
                if (j + 1 <= C)
                     dp[x][i][j] += dp[!x][i-1][j+1]*(j+1)/C;
            }
        }
    } 
    
    int main() {
        while (scanf("%d", &C), C) {
            scanf("%d %d", &N, &M); 
            if (N == 0 && M == 0) { 
                printf("%.3lf\n", 1.);
                continue;
            }
            if ((N&1)^(M&1) || M > C || M > N) {
                printf("%.3lf\n", 0.);
                continue;
            }
            if (N > 1000) {
                N = N & 1 ? 1001 : 1000;
            }
            DP();
            printf("%.3lf\n", dp[N&1][N][M]);
        }
        return 0;    
    } 
  • 相关阅读:
    Vue项目中使用Vue-Quill-Editor富文本编辑器插件
    Element-UI中的Cascader 级联选择器高度以及位置问题
    Sublime中同一个文件进行分屏显示
    Oracle的clob数据类型
    查看Nginx版本号的几种方式
    华为路由器EasyNAT&NAT Server
    huawei路由器NAT配置
    15
    14
    13
  • 原文地址:https://www.cnblogs.com/Lyush/p/2857203.html
Copyright © 2020-2023  润新知