zoukankan      html  css  js  c++  java
  • POJ1322Chocolate--概论DP

    题目在这里

    每次从包装中取出一块巧克力并放在桌子上。如果桌子上有两个相同颜色的巧克力,则将这两个丢掉。
    如果包中有C种颜色的巧克力(颜色均匀分布),从包装中取出N个巧克力后,桌子上确实有M个巧克力的概率是多少?
    对于每种情况,存在三个非负整数:C(C <= 100),N和M(N,M <= 1000000)。 

    题目要求取出n个巧克力后,桌上剩余m个巧克力的概率。那我们就按着题目意思来,dp[i][j]的含义就是这个
    首先,判断边界条件,如果取出0个巧克力,那么桌子上剩余0个巧克力的概率是多少???很简单,dp[0][0] = 1;
    另外,针对输入的c,n,m进行非法判断,即概率为0.000的直接输出就好了
     
    m的个数是小于等于c的,因为如果某种颜色的巧克力数量是大于等于2的,那么一定是两个都被拿走了,也就是最后剩下的每种巧克力要么只有一个要么没有。所以最多所有的颜色都在桌上,都是一个
    dp[i][j]表示前i次操作(即取出i个巧克力)后,桌上出现j个巧克力的概率。试想,如果i+j是奇数会是什么情况?
    dp[i][j]是等于0的(不可能出现的情况)。为什么不可能出现呢,因为每次取出的球都会现放到桌上比较,如果没有重复的颜色,则桌子上球数+1,如果有重复,将重复的两个球都拿掉,也就是i的次数首先加到m上,此刻的m要么不变,要么-2,不会出现奇数的情况。所以dp[i][j]中i+j为奇数则概率是0
    可以手动模拟验算下。
     
    那么,状态转移方程怎么来呢??因为么取到的球和桌子上球的颜色不重复,即 dp[i-1][j-1]  * (c-j+1.0)/c; 就是在前面拿出i-1个巧克力后,桌子剩余j-1个巧克力的概率上,乘上这次取出的巧克力与桌子上巧克力颜色不重复的概率,c-j+1.0,表示颜色总数减去桌上的不同颜色的,剩余的也是不同颜色的,再除以c就是对应的取出不同颜色的概率了
    要么取出的球和桌上某个球的颜色相同,要一起拿走,方程是这样:dp[i-1][j+1]*(j+1.0)/c ,j+1/c,即取出的球的颜色和桌上的球的某个颜色相同了
    dp[i][j]将二者加起来即可
     
    另外,在对很大的n进行计算时,可以将其看成一个较小的n,因为很大的n对应的概率和较小的数m的概率只有小数点后好几位才会不同,所以可以转换下
     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 using namespace std;
     5 #define MAX 105 
     6 int main()
     7 {
     8     int c = 0, n = 0, m = 0;
     9     double dp[MAX * 10][MAX];
    10     while (scanf("%d", &c) != EOF)
    11     {
    12         if (c == 0)
    13         {
    14             break;
    15         }
    16         scanf("%d %d", &n, &m);
    17         if (m > c || m > n || (m + n) % 2 != 0)//特判
    18         {
    19             printf("0.000
    ");
    20             continue;
    21         }
    22         memset(dp, 0, sizeof(dp));
    23         if (n > 1000)//将较大的n转换较小的
    24         {
    25             n = 1000 + n % 2;//奇偶选择
    26         }
    27         dp[0][0] = 1;
    28         for (int i = 1; i <= n; ++i)
    29         {
    30             for (int j = 0; j <= c; ++j)
    31             {
    32                 if ((i + j) % 2 != 0)
    33                 {
    34                     continue;
    35                 }
    36                 dp[i][j] = dp[i - 1][j - 1] * (c - j + 1.0) / c + dp[i - 1][j + 1] * (j + 1.0) / c;
    37             }
    38         }
    39         printf("%.3lf
    ", dp[n][m]);
    40     }
    41     return 0;
    42 }
     
  • 相关阅读:
    linux学习笔记31--命令route和routetrace
    你大概走了假敏捷:认真说说敏捷的实现和问题【转】
    如何管理好自己的测试团队【转】
    Linux 服务器配置JDK
    替换jar包内指定的文件
    Jenkins maven仓库地址 和 手动修改maven 版本
    逻辑英语 第四季 Speaking and Listening
    Linux下,部署多个Tomcat
    逻辑英语 第三季
    Jmeter+Ant+Jenkins接口自动化测试框架搭建
  • 原文地址:https://www.cnblogs.com/ygsworld/p/11329954.html
Copyright © 2011-2022 走看看