zoukankan      html  css  js  c++  java
  • 剑指Offer

    剑指Offer - 九度1360 - 乐透之猜数游戏
    2014-02-05 19:54
    题目描述:

    六一儿童节到了,YZ买了很多丰厚的礼品,准备奖励给JOBDU里辛劳的员工。为了增添一点趣味性,他还准备了一些不同类型的骰子,打算以掷骰子猜数字的方式发放奖品。例如,有的骰子有6个点数(点数分别为1~6),有的骰子有7(点数分别为1~7),还有一些是8个点数(点数分别为1~8) 。他每次从中拿出n个同一类型的骰子(假设它们都是拥有m个点数并且出现概率相同)投掷,然后让员工在纸上按优先级(从高到低)的顺序写下3个数上交,表示他们认为这些骰子最有可能的点数之和是多少。第一个数就猜对的人,是一等奖;第二个数才猜对的人是二等奖;如果三个数都不是正确答案,别灰心!YZ还准备了很多棒棒糖。ZL很聪明,他想了想,打算把概率(以保留两位小数的概率计)最高的三个数找出来,如果有概率相同,则选择其中点数和最小的那个数。你觉得ZL会依次写下哪三个数?

    输入:

    输入有多组数据。

    每组数据一行,包含2个整数n(0<=n<=10),m(6<=m<=8),n表示YZ拿出的骰子数,m表示骰子拥有的点数。如果n=0,则结束输入。

    输出:

    对应每组数据,输出ZL最可能依次写下的点数,以及其对应的概率值。概率值按45入要求保留2位小数。每组数据之间空一行,注意:最后一组数据末尾无空行。

    样例输入:
    1 6
    4 6
    3 7
    0
    样例输出:
    1 0.17
    2 0.17
    3 0.17
    
    13 0.11
    14 0.11
    15 0.11
    
    12 0.11
    10 0.10
    11 0.10
    题意分析:
      扔骰(tou,不是shai)子求点数应该也是很常见的概率问题了。对于一个点数范围1~m的骰子,扔了n次,求出点数之和概率最大的三个值,以及对应的概率。
      首先,扔一次获得各个点数的概率是相等的,因此各点数之和的概率分布一定是对称的,所以概率最大的一定就是正中间的三个点数和。因此,均值n*(1+m)/2就是概率最大的。考虑到奇偶和取整问题,在n奇m偶的情况下,概率最大的点数有两个。
      如果你做过另一个题:求x+y+z=n的非负整数解,应该会想在这题上试试用组合数学来搞出个巧妙解法。但由于这道题中限制每个数都在1~m的范围内,需要分情况处理。所以我还是决定用n^2*m规模的动态规划来解决。
      k个骰子能扔出的点数之和最小是k,最大是m*k,因此只要知道了k-1个骰子的所有扔法,就能推导出k个骰子的所有扔法的概率分布。
      递推公式为:
        1. 用a[n][k]表示n个骰子扔出的点数和为k的扔法个数。
        2. a[1][j]=1, j=[1,m]
        3. a[i][j]=sigma(a[i-1][k]), j=[i,i*m], k∈[i-1,(i-1)*m]∩[j-m,j-1]
      由于递推需要进行n轮,每轮的点数之和从i到i*m。所以时间复杂度是O(n*(n*m)),也就是O(n^2*m),空间复杂度可以优化为O(n*m),不过本题中n和m都比较小,所以我没有进一步优化。
      最后需要注意的,是对算出来的概率四舍五日到小数点后两位,然后再比较概率。
     1 // 689492    zhuli19901106    1360    Accepted    点击此处查看所有case的执行结果    1024KB    1230B    10MS
     2 // 201402030320
     3 #include <algorithm>
     4 #include <cstdio>
     5 #include <cstring>
     6 #include <vector>
     7 using namespace std;
     8 
     9 typedef struct st{
    10 public:
    11     int x;
    12     int y;
    13     st(int _x = 0, int _y = 0): x(_x), y(_y) {};
    14 }st;
    15 
    16 bool comparator(const st &a, const st &b)
    17 {
    18     if (a.y == b.y) {
    19         return a.x < b.x;
    20     } else {
    21         return a.y > b.y;
    22     }
    23 }
    24 
    25 int main()
    26 {
    27     int n, m;
    28     int i, j, k;
    29     int sum;
    30     int a[11][81];
    31     vector<st> v;
    32     int cc;
    33 
    34     cc = 0;
    35     while (scanf("%d", &n) == 1 && n) {
    36         scanf("%d", &m);
    37         if (cc > 0) {
    38             printf("
    ");
    39         }
    40         ++cc;
    41         memset(a, 0, 11 * 81 * sizeof(int));
    42         for (i = 1; i <= m; ++i) {
    43             a[1][i] = 1;
    44         }
    45         sum = m;
    46         for (i = 2; i <= n; ++i) {
    47             for (j = 1; j <= m; ++j) {
    48                 for (k = i - 1; k <= (i - 1) * m; ++k) {
    49                     a[i][k + j] += a[i - 1][k];
    50                 }
    51             }
    52             sum *= m;
    53         }
    54 
    55         for (i = n; i <= n * m; ++i) {
    56             v.push_back(st(i, (int)(100.0 * a[n][i] / sum + 0.5)));
    57         }
    58         
    59         sort(v.begin(), v.end(), comparator);
    60 
    61         for (i = 0; i < 3; ++i) {
    62             printf("%d %.2f
    ", v[i].x, v[i].y / 100.0);
    63         }
    64         v.clear();
    65     }
    66 
    67     return 0;
    68 }
  • 相关阅读:
    收藏文章整理
    关于java里的SimpleDateFormat使用
    手写MQ框架(四)-使用netty改造梳理
    JDK8中的ConcurrentHashMap源码
    JDK8中的HashMap源码
    手写MQ框架(三)-客户端实现
    手写MQ框架(二)-服务端实现
    Vue.js入门
    Tomcat启动找不到项目依赖jar的解决方式
    java课堂 动手动脑2
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3538410.html
Copyright © 2011-2022 走看看