zoukankan      html  css  js  c++  java
  • [GeeksForGeeks] Count Number of ways to reach a given score in a game

    Consider a game where a player can score 3 or 5 or 10 points in a move. Given a total score n, find the number of 

    ways to reach the given score. 

    Example:

    Input n = 20

    Output: 4

    There are the following 4 ways to reach 20.

    (10, 10)

    (5, 5, 10)

    (5, 5, 5, 5)

    (3, 3, 3, 3, 3, 5)

     Solution 1. DFS + Backtracking

    Since we do not consider the same combination with different ordering different ways, this problem is equivalent to a simpler 

    version of Combination Sum II. The given set does not have duplicate values, and each element can be picked unlimited times.

    Algorithm:

    1. sort the input points array.

    2.  start from the first element, recursively add it to the current selection and check if the remaining score can be obtained 

    from the current considering element set. When startIdx is 0, we consider all elements, when it is 1, we exclude element 0 

    as all cases that involves element 0 have been checked. 

    The key point in the recursive call is that we do not advance the startIdx from i to i + 1 as each element can be picked unlimited times. 

     1 import java.util.ArrayList;
     2 import java.util.Arrays;
     3 
     4 public class CountWaysOfScore {
     5     private int ways = 0;
     6     private ArrayList<ArrayList<Integer>> results;
     7     public int getWaysofScore(int[] points, int score) {
     8         results = new ArrayList<ArrayList<Integer>>();
     9         if(score > 0 && (points == null || points.length == 0)) {
    10             return 0;
    11         }
    12         if(score == 0) {
    13             return 1;
    14         }
    15         Arrays.sort(points);
    16         getWaysHepler(points, 0, score, new ArrayList<Integer>(), results);
    17         return ways;
    18     }
    19     private void getWaysHepler(int[] points, int startIdx, int score, 
    20                                 ArrayList<Integer> list, ArrayList<ArrayList<Integer>> results) {
    21         if(score == 0) {
    22             ways++;
    23             results.add(new ArrayList<Integer>(list));
    24             return;
    25         }
    26         else if(points[startIdx] > score) {
    27             return;
    28         }
    29         int remainScore = score;
    30         for(int i = startIdx; i < points.length; i++) {
    31             remainScore -= points[i];
    32             list.add(points[i]);
    33             getWaysHepler(points, i, remainScore, list, results);
    34             remainScore += points[i];
    35             list.remove(list.size() - 1);
    36         }
    37     }
    38     public static void main(String[] args) {
    39         int[] points = {3, 5, 10};
    40         CountWaysOfScore test = new CountWaysOfScore();
    41         System.out.println(test.getWaysofScore(points, 20));
    42         for(int i = 0; i < test.results.size(); i++) {
    43             for(int j = 0; j < test.results.get(i).size(); j++) {
    44                 System.out.print(test.results.get(i).get(j) + " ");
    45             }
    46             System.out.println();
    47         }
    48     }
    49 }

    Solution 2. Dynamic Programming 

    State: T[i][j]: the total ways of score i for given the first j elements points[0.....j - 1]

    Function: if points[j - 1] <= i, it means the current point[j - 1] can be possibly used: T[i][j] = T[i - points[j - 1]][j] + T[i][j - 1];

         if not, then points[j - 1] can not be used: T[i][j] = T[i][j - 1];

    Initialization: T[0][j] = 1;  if score is 0, then there is 1 way to get 0 by not picking anything.

          T[i][0] = 0, i >= 1; if score is bigger than 1 and we don't have any elements to pick, there is 0 way.

    Answer: T[score][points.length]

     1 public int getWaysOfScoreDp(int[] points, int score) {
     2     if(points == null || score < 0) {
     3         return 0;
     4     }
     5     int[][] T = new int[score + 1][points.length + 1];
     6     for(int j = 0; j <= points.length; j++) {
     7         T[0][j] = 1;
     8     }
     9     for(int i = 1; i <= score; i++) {
    10         T[i][0] = 0;
    11     }
    12     for(int i = 1; i <= score; i++) {
    13         for(int j = 1; j <= points.length; j++) {
    14             if(points[j - 1] <= i) {
    15                 T[i][j] = T[i - points[j - 1]][j] + T[i][j - 1];
    16             }
    17             else {
    18                 T[i][j] = T[i][j - 1];
    19             }
    20         }
    21     }
    22     return T[score][points.length];
    23 }

    Follow up question: instead of only return the total number of ways, hwo about return all possible ways?

    Related Problems

    Combination Sum

    Combination Sum II

  • 相关阅读:
    *三维数组的初始化及遍历三个for循环
    *二维数组的初始化
    用while判读循环语句1+1/2!+1/3!+...1/20!的和阶乘的计算方法 式:n!=n*(n-1)!
    求一组数组各个元素的和*
    *求一组数组各个元素的和*
    使用for循环输出杨辉三角-还是不懂得需要复习
    使用for循环输出空心的菱形的思路-还是没有办法理解
    Break用法再举例
    continue用来结束本次循环 break用来结束整个循环体
    LeetCode.1154-一年中的第几天(Day of the Year)
  • 原文地址:https://www.cnblogs.com/lz87/p/7462911.html
Copyright © 2011-2022 走看看