Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonでn個のキャンディーをk個のバッグに配布する組み合わせの数を求めるプログラム


n個のキャンディーと、それらを入れるためのk個のバッグがあるとします。このとき、各バッグに必ず1個以上のキャンディーが入るように配布する方法が何通りあるかを求める問題です。ここでのポイントは、すべてのキャンディーが互いに異なる(ユニークな)ものであるという点です。そのため、どのキャンディーをどのバッグに入れるかという組み合わせをすべて数え上げる必要があります。

例えば、入力が n = 3、k = 2 の場合、出力は 3 になります。

具体的には、キャンディーは次の3通りの方法で配分できます。

(1, 2), (3)
(1), (2, 3)
(2), (1, 3)

解法のアプローチ:動的計画法(DP)

この問題は、動的計画法を使うことで効率的に解くことができます。考え方の手順は以下のとおりです。

  • dp := サイズ n × n の行列を用意し、すべての要素を 1 で初期化する

  • c を 2 から n まで繰り返す:

    • b を 1 から min(c, k) まで繰り返す:

      • dp[c, b] := dp[c-1, b-1] + dp[c-1, b] × (b+1)

  • dp[n-1, k-1] を結果として返す

この漸化式の意味を整理してみましょう。c番目のキャンディーを処理するとき、次の2つのケースが考えられます。

  • 新しいバッグに入れる場合: 残りのキャンディーで b-1 個のバッグを埋める方法は dp[c-1, b-1] 通り

  • すでにあるバッグに入れる場合: 既存の b+1 個のバッグのいずれかを選べるので、dp[c-1, b] × (b+1) 通り

この2つを足し合わせることで、全体の配布方法の数が求まります。

実装例

以下のPythonコードで、実際の動作を確認できます。

def solve(n, k):
   dp = [[1] * n for _ in range(n)]
   for c in range(2, n):
      for b in range(1,min(c,k)):
         dp[c][b] = dp[c-1][b-1] + dp[c-1][b] * (b+1)
   return dp[n-1][k-1]

print(solve(3, 2))

入力

3, 2

出力

3

  1. Pythonで行列内の「完全に囲まれた島」の数を数える方法を解説

    問題の概要0と1のみで構成された2次元のバイナリ行列を考えます。ここで「1」は陸地、「0」は水を表します。島とは、隣り合った1の集まりであり、その周囲がすべて水で囲まれている領域のことです。本記事では、行列の中から端(境界)に一切接しておらず、完全に水で囲まれた島の数を数えるプログラムをPythonで実装する方法を解説します。例として、次のような入力が与えられた場合を考えてみましょう。この場合の出力は 2 となります。島は全部で3つ存在しますが、そのうち2つだけが完全に水で囲まれているためです。解法のアプローチ:DFS(深さ優先探索)この問題は、DFS(深さ優先探索)を用いることで効率的に解く

  2. セットを使って文字列内の母音の数をカウントするPythonプログラム

    本記事では、Pythonを使って文字列内に含まれる母音の数をカウントする方法について解説します。セット(set)を活用した効率的な実装を中心に、初心者の方にもわかりやすく説明していきます。 問題の概要 問題文:任意の文字列が与えられたとき、その文字列に含まれる母音の数をセットを使って数えます。 基本的なアプローチとしては、文字列全体を先頭から順に走査し、各文字が母音であるかどうかを判定します。母音であればカウントを1ずつ増やしていき、最終的な合計を出力します。 実装例 def vowel_count(str_): count = 0 # 母音をセットとして定義 vowe