计算可能组合的数量以达到与骰子的总和

时间:2017-01-11 08:33:09

标签: algorithm

假设您需要n个步骤(例如100个)访问Monopoly的起点, 滚动模具多少组合再次到达起点。

最小投掷数是向上舍入(n / 6),最大值是n(投掷1次n次)。

n可能大于10000.但除了暴力之外我无法想到更好的解决方案。

2 个答案:

答案 0 :(得分:4)

这取决于订单是否重要。

让我们说它没有。那是, 抛出1,2,3与投掷3,2,1相同。在这种情况下,这个Scala片段应该可以正常工作。

  def count(n: Int): Int = {
    def count(n: Int, dots: List[Int]): Int = dots match {
      case _ if n == 0 => 1
      case h :: t if n > 0 => count (n - h, h :: t) + count (n, t)
      case _ => 0
    }
    count(n, List(1, 2, 3, 4, 5, 6))
  }

如果订单比这更重要,那就是解决方案。

import java.math.BigInteger;
import java.util.LinkedList;

public class HexabonacciSolver {

    public BigInteger solve(int n) {
        LinkedList<BigInteger> lastSix = new LinkedList<>();
        lastSix.add(new BigInteger("1"));
        lastSix.add(new BigInteger("2"));
        lastSix.add(new BigInteger("4"));
        lastSix.add(new BigInteger("8"));
        lastSix.add(new BigInteger("16"));
        lastSix.add(new BigInteger("32"));
        if (n < 7)
            return lastSix.get(n - 1);
        for (int i = 0; i < n - 6; i++){
            lastSix.add(lastSix.get(0).add(lastSix.get(1).add(lastSix.get(2).add(lastSix.get(3).add(lastSix.get(4).add(lastSix.get(5)))))));
            lastSix.removeFirst();
        }
        return lastSix.get(5);
    }

}

说明:它是如何工作的?

假设您想知道在Monopoly中有多少不同的骰子卷序列进入字段100。你知道要到达那里,之前的卷必须是6,5,4,3,2或1.如果你只需要到达字段94,95,96,97所需的不同卷序列的数量, 98,99你可以把它们总结起来并得到100字段的解决方案。这正是程序所做的。这非常类似于Fibonacci序列的构建方式,区别在于序列中的下一个数字是通过总计6个先前的数字来计算的(因此名称为“Hexabonacci”)

解决方案在时间上是线性O(N),在空间中是常数O(C),因为我们只需要存储 Hexabonacci 序列的6个最后数字。 由于n = 10000的结果有数百个数字,因此Java解决方案返回一个BigInteger。

如果您希望在Scala / Python / JavaScript中看到解决方案,请告诉我。

答案 1 :(得分:4)

简单的动态编程可以解决这个问题

#include<bits/stdc++.h>
using namespace std;
int n;
int dp[100010] = {0};
int main() {
    cin >> n;
    dp[0] = dp[1] = 1;
    for(int i=2; i<=n ; i++){
        for(int j=1; j<=6; j++)
            if(i - j >= 0)
                dp[i] += dp[i-j];
    }
    cout << dp[n] << endl;
    return 0;
}

dp[x]定义为有序组合的总数#,以实现总和x,每步使用1到6个,

然后dp[x] = sum (dp[x - i]) where 1 <= i <= 6 and x-i >= 0

基本情况为dp[0] = dp[1] = 1

需要注意的一点是,这个数字正在快速增长,你可能需要使用long long / 64bit整数来存储结果

例如,要实现总共4个步骤,

dp(4)= dp(3)+ dp(2)+ dp(1)+ dp(0)

= 4 + 2 + 1 + 1

= 8

对应[1,2,1],[2,1,1],[1,1,1,1],[3,1],[2,2],[1,1,2] ,[1,3],[4]