解题笔记(18)――n个骰子的点数 - wuzhekai的专栏 - 博客频道 - CSDN.NET


解题笔记(18)――n个骰子的点数 - wuzhekai的专栏 - 博客频道 - CSDN.NET
问题描述:n个骰子扔在地上,所有骰子朝上一面的点数之和为S。输入n,打印出S的所有可能的值出现的概率。
         思路:这是一道应用动态规划思想的题目,而动态规划最难的就是要找最优子结构。并采取一种称为备忘录的方法避免重复计算。因为备忘录方法为每个解过的子问题建立了备忘录,以备需要时参看,避免了相同子问题的重复求解。
        本题的最优子结构为:F(k, n) 表示k个骰子点数和为n的种数,k表示骰子个数,n表示k个骰子的点数和
                 /       = F(k-1, n-6) + F(k-1, n-5) + F(k-1, n-4) + F(k-1, n-3) + F(k-1, n-2) + F(k-1, n-1)        对于 k > 0, k <= n <= 6*k
 F(k, n) =     
                 \       = 0              对于 n < k or n > 6*k


         当k=1时, F(1,1)=F(1,2)=F(1,3)=F(1,4)=F(1,5)=F(1,6)=1。

         从上面公式可以看出,k个骰子点数和为n的种数只与k-1个骰子的和有关。这就可以用到备忘录的方法,用一张表格保存已解决的子问题的解,然后自底向上填表。考虑到当前层的计算只与下一层有关,因此只需保存一行。
[剑指offer] 面试题43:n个骰子的点数(Java)
分析: 一般来说骰子只有6面,点数为1~6,故n个骰子的最小和为n,最大和为6*n,则n个骰子的点数之和出现的频数可以用一个数组来保存,大小为6*n-n。
思路1:最直接的方法是求出n个骰子点数的全排列,然后一一计算其和值,统计,最后算出每个和值的概率,这里使用基于递归的方法来求各和值的频数.先把n个骰子分为两堆:第一堆只有一个,另一个有n-1个。单独的那一个有可能出现从1到6的点数。我们需要计算从1到6的每一种点数和剩下的n-1个骰子来计算点数和。接下来把剩下的n-1个骰子还是分成两堆,第一堆只有一个,第二堆有n-2个。我们把上一轮那个单独骰子的点数和这一轮单独骰子的点数相加,再和剩下的n-2个骰子来计算点数和。
    private int gMaxValue = 6;
     
    public void probility(int orignal, int current, int sum, int[] probilities){
        if(current == 1){
            probilities[sum - orignal]++;
        }else{
            for(int i=1; i<= gMaxValue; i++){
                probility(orignal, current - 1, sum + i, probilities);
            }
        }
    }
     
    public void probility(int number, int[] probilities){
        for(int i=1; i<= gMaxValue; i++){
            probility(number,number, i,probilities);
        }
    }
     
    public void printProbability(int number){
        if(number < 1)
            return;
        int maxSum = number * gMaxValue;
         
        int[] probilities = new int[maxSum - number + 1];
        probility(number, probilities);
         
        double total = Math.pow(gMaxValue, number);
         
        for(int i=number; i<= maxSum; i++){
            double ratio = probilities[i - number] / total;
            System.out.println(i + ": " + ratio);
        }
    }
     
    public static void main(String[] args){
        int number = 5;
        new PrintSumProbabilityOfDices().printProbability(number);
    }
  1.     public static void printProbabilityOfDice(int n){  
  2.         if(n<1){  
  3.             return;  
  4.         }  
  5.         double total=Math.pow(MAX, n);   
  6.         int len=n*MAX-n*1+1;//the sum of n dices is from n*1 to n*MAX  
  7.         int[] times=new int[len];  
  8.         for(int i=1;i<=MAX;i++){//initial the first dice.  
  9.             probabilityOfDice(n,i,n,0,times);//count the times of each possible sum  
  10.         }  
  11.         for(int i=0;i<len;i++){  
  12.             System.out.println((i+n)+","+times[i]+"/"+total);  
  13.         }  
  14.           
  15.     }  
  16.     public static void probabilityOfDice(int n,int curDiceValue,int numOfDices,int curSum,int[] times){  
  17.         if(numOfDices==1){  
  18.             int sum=curSum+curDiceValue;  
  19.             times[sum-n]++;//n*1 to n*MAX <---> 0 to len  
  20.         }else{  
  21.             int sum=curSum+curDiceValue;  
  22.             for(int i=1;i<=MAX;i++){  
  23.                 probabilityOfDice(n,i,numOfDices-1,sum,times);  
  24.             }  
  25.         }  
  26.     } 
XX. 我们可以考虑用两个数组来存储骰子点数每一总数出现的次数。在一次循环中,第一个数组中的第n个数字表示骰子和为n出现的次数。那么在下一循环中,我们加上一个新的骰子。那么此时和为n的骰子出现的次数,应该等于上一次循环中骰子点数和为n-1n-2n-3n-4n-5n-6的总和。所以我们把另一个数组的第n个数字设为前一个数组对应的第n-1n-2n-3n-4n-5n-6之和。
上述代码没有在函数里把一个骰子的最大点数硬编码(hard code)6,而是用一个变量g_maxValue来表示。这样做的好处时,如果某个厂家生产了最大点数为4或者8的骰子,我们只需要在代码中修改一个地方,扩展起来很方便。如果在面试的时候我们能对面试官提起对程序扩展性的考虑,一定能给面试官留下一个很好的印象。
public void printProbability_2(int number){
    if(number < 1)
        return;
    int maxSum = gMaxValue * number + 1;
    int[][] probilities = new int[2][maxSum];
    int flag = 0;
    for(int i=1; i<=gMaxValue; i++)
        probilities[flag][i] = 1;
     
    for(int i=2; i<= number; i++){
        for(int j = 0;  j<i; j++)
            probilities[1-flag][j] = 0;
        for(int j = i; j<=gMaxValue * i; j++){
            probilities[1-flag][j] = 0;
            for(int k=1; k<=j && k<=gMaxValue; k++)
                probilities[1-flag][j] += probilities[flag][j-k];
        }
        flag = 1 - flag;
    }
    double total = Math.pow(gMaxValue, number);
    for(int i=number; i< maxSum; i++){
        double ratio = probilities[flag][i] / total;
        System.out.println(i + ": " + ratio);
    }
}
XXX: DP
http://bylijinnan.iteye.com/blog/1428099
  1.     /* 
  2. 有k-1个骰子时,再增加一个骰子,这个骰子的点数只可能为1、2、3、4、5或6。那k个骰子得到点数和为n的情况有: 
  3. (k-1,n-1):第k个骰子投了点数1 
  4. (k-1,n-2):第k个骰子投了点数2 
  5. (k-1,n-3):第k个骰子投了点数3 
  6. .... 
  7. (k-1,n-6):第k个骰子投了点数6 
  8. 在k-1个骰子的基础上,再增加一个骰子出现点数和为n的结果只有这6种情况! 
  9. 所以:f(k,n)=f(k-1,n-1)+f(k-1,n-2)+f(k-1,n-3)+f(k-1,n-4)+f(k-1,n-5)+f(k-1,n-6) 
  10. 初始化:有1个骰子,f(1,1)=f(1,2)=f(1,3)=f(1,4)=f(1,5)=f(1,6)=1。 
  11.      */  
  12.     public static void printProbabilityOfDice2(int n){  
  13.         if(n<1){  
  14.             return;  
  15.         }  
  16.         double total=Math.pow(MAX, n);   
  17.         int maxSum=n*MAX;  
  18.         double[][] f=new double[n+1][n*MAX+1];  
  19.         for(int i=1;i<=MAX;i++){  
  20.             f[1][i]=1;  
  21.         }  
  22.         for(int k=2;k<=n;k++){  
  23.             for(int sum=n;sum<=maxSum;sum++){  
  24.                 for(int i=1;sum-i>=1&&i<=MAX;i++){  
  25.                     f[k][sum]+=f[k-1][sum-i];  
  26.                 }  
  27.             }  
  28.         }  
  29.           
  30.         for(int sum=n;sum<=maxSum;sum++){  
  31.             System.out.println(sum+","+f[n][sum]+"/"+total);  
  32.         }  
  33.     }
Read full article from 解题笔记(18)――n个骰子的点数 - wuzhekai的专栏 - 博客频道 - CSDN.NET

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts