Sobes.tech
Back to questions
Middle — Senior
9

Как изменить решение для подсчёта сумм и комбинаций игральных кубиков, если количество кубиков параметр?

Companies where asked
OZONOZON

Answer from AI

sobes.tech AI

Что хотят услышать интервьюеры:

Нужно показать, что решение масштабируется на произвольное число кубиков, а не жёстко зашито под конкретный случай. Обычно это означает переход от перебора всех комбинаций к динамическому программированию по количеству кубиков и сумме. Важно уметь оценить сложность и правильно задать состояния DP.

Определение:

Если число кубиков — параметр, задачу удобно формулировать так: посчитать, сколькими способами можно получить каждую сумму после броска n кубиков. Для этого используют динамическое программирование: dp[i][s] — число способов набрать сумму s с помощью i кубиков. Переход строится через добавление очередного кубика с гранями от 1 до 6.

Пример использования:

Например, нужно узнать, сколькими способами можно выбросить сумму 10 на 3 шестигранных кубиках.

package main

import "fmt"

func countWays(dice, target int) int {
	dp := make([][]int, dice+1)
	for i := range dp {
		dp[i] = make([]int, target+1)
	}

	dp[0][0] = 1

	for i := 1; i <= dice; i++ {
		for sum := 1; sum <= target; sum++ {
			for face := 1; face <= 6; face++ {
				if sum-face >= 0 {
					dp[i][sum] += dp[i-1][sum-face]
				}
			}
		}
	}

	return dp[dice][target]
}

func main() {
	fmt.Println(countWays(3, 10))
}

Пояснение кода:

Код считает количество вариантов получить заданную сумму после dice бросков.

  1. dp[0][0] = 1 — базовый случай: ноль кубиков дают сумму 0 ровно одним способом.
  2. Для каждого количества кубиков i перебирается текущая сумма sum.
  3. Для каждого значения грани face от 1 до 6 смотрится, можно ли прийти к sum из предыдущего состояния sum-face.
  4. Если можно, то число способов добавляется из dp[i-1][sum-face].
  5. В итоге dp[dice][target] содержит ответ.

Это решение легко обобщается: если у кубика не 6 граней, а m, то цикл по face просто идёт от 1 до m.

Ключевые моменты:

  • При переменном числе кубиков лучше использовать DP, а не полный перебор всех комбинаций.
  • Состояние обычно задают как dp[i][s]: число способов получить сумму s на i кубиках.
  • Переход: dp[i][s] += dp[i-1][s-face] для всех допустимых значений грани.
  • Сложность базовой реализации: O(n * target * faces), где faces — число граней.
  • Если нужно только число способов для одной суммы, память можно оптимизировать до двух строк или одного массива.
  • Решение легко адаптируется под кубики с разным числом граней или дополнительные ограничения.