掷骰子

Description:

描述:

In this article, we are going to see a dynamic programing problem which can be featured in any interview rounds.

在本文中,我们将看到一个动态的编程问题,该问题可以在任何采访回合中体现。

Problem statement:

问题陈述:

Given n dice each with m faces, numbered from 1 to m, find the number of ways to get sum X. X is the summation of values on each face when all the dice are thrown.

给定n个骰子,每个骰子有m个面(从1m编号),请找到获得和X的方法数量。 X是抛出所有骰子时每个面上的值之和。

    Input:
    n=3
    m=3
    X=6

    Output:
    Total number of ways are: 7

Explanation:

说明:

    Total number of dices: 3 say x1,x2,x3
    Number of faces on each dice: 3 (1 to 3)
    Total sum to be achieved: 6
    We will write as xi(j)which means face value of dice xi is j 
    So sum 6 can be achieved in following ways:
    6=x1(1)+x2(2)+x3(3)
    6=x1(1)+x2(3)+x3(2)
    6=x1(2)+x2(2)+x3(2)
    6=x1(2)+x2(3)+x3(1)
    6=x1(2)+x2(1)+x3(3)
    6=x1(3)+x2(2)+x3(3)
    6=x1(3)+x2(3)+x3(1)

    This are total 7 ways to achieve the sum.

Solution Approach:

解决方法:

If it was only 1 dice, then if X<=m, the answer would be 1 else 0. Since there is only one way to achieve the sum if possible as there is only one dice.

如果只有1个骰子,那么如果X <= m ,答案将是1否则为0。由于只有一种骰子,因此只有一种方法可以实现总和。

Now when n, number of dice>1, then the problem becomes a recursive one

现在,当n ,骰子数> 1时,问题就变成了递归问题

We can think of the recursive function as f(n,X) where n is number of dice and X is desired sum.

我们可以将递归函数视为f(n,X) ,其中n是骰子数, X是期望的和。

A single dice has m choices, which means the face can have values ranging 1 to m
So,

一个骰子有m个选择,这意味着该面Kong的取值范围为1到m
所以,

Recursively we can write,

我们可以递归地写

dice throw formula

That means summation of all choices for this particular dice to have face value 1 to minimum(X, m)

这意味着该特定骰子的所有选择的总和的面值为1到最小值(X,m)

For our example case, n=3, m=3, X=6

对于我们的示例情况, n = 3,m = 3,X = 6

So, we need to find f(3,6)

因此,我们需要找到f(3,6)

    f(3,6)=f(2,5)+f(2,4)+f(2,3)

f(2,5), f(2,4), f(2,3) all are sub problems themselves which are needed to be solved further. This would generate a recursion tree.

f(2,5),f(2,4),f(2,3)本身都是子问题,需要进一步解决。 这将生成一个递归树。

Of course, we have base cases for single dice which is f(1,i)=1 for i=1 to m

当然,我们有单个骰子的基本情况, 对于i = 1到m,f(1,i)= 1

But this recursion will generate many overlapping sub problems, hence, we need to convert it to dynamic programing.

但是这种递归将产生许多重叠的子问题,因此,我们需要将其转换为动态编程。

    1)  Declare dp[n+1][x+1] similar to f(n,x). Initialize it to 0.
    2)  Implement the base case f(1,i)
        for i=1 to i minimum(m ,x)
            dp[1][i]=1;
    3)  Fill the other values as per recursion relation
        for i=2 to n //iterate for number of dices
            for j=1 to x //iterate for sums
                for k=1 to minimum(m ,j)
                    //iterate for face values up to minimum(m,j),j be the subsum
                    dp[i][j]+=dp[i-1][j-k];
                end for
            end for
        end for    

    4)  The answer is dp[n][x]

C++ Implementation:

C ++实现:

#include <bits/stdc++.h>

using namespace std;

long long int dicethrow(int m, int n, int x) {
  if (m * n < x)
    return 0;

  long long dp[n + 1][x + 1];
  memset(dp, 0, sizeof(dp));

  //base case
  for (int i = 1; i <= m && i <= x; i++)
    dp[1][i] = 1;

  for (int i = 2; i <= n; i++) { //iterate for number of dices
    for (int j = 1; j <= x; j++) { //iterate for sums
      //iterate for face values up to minimum(m,j),j be the subsum
      for (int k = 1; k <= m & k < j; k++) {
        dp[i][j] += dp[i - 1][j - k];
      }
    }
  }
  return dp[n][x];

}
int main() {
  int n, m, x;

  cout << "Enter number of dices, n:\n";
  cin >> n;
  cout << "Enter number of faces on a dice, m:\n";
  cin >> m;
  cout << "Enter sum, X:\n";
  cin >> x;
  cout << "Number of ways to achieve sum: " << dicethrow(m, n, x) << endl;

  return 0;
}

Output

输出量

RUN 1:
Enter number of dices, n:
3
Enter number of faces on a dice, m:
3
Enter sum, X:
6
Number of ways to achieve sum: 7

RUN 2:
Enter number of dices, n:
3
Enter number of faces on a dice, m:
3
Enter sum, X:
12
Number of ways to achieve sum: 0

In the second output there is no way to acquire the sum which can be verified as m*n<X. It's better practise to keep such base case to optimize your code :)

在第二个输出中,无法获取可以验证为m * n <X的和 。 最好保留此类基本情况以优化代码:)

翻译自: https://www.includehelp.com/icp/dice-throw.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值