Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

Number of Dice Rolls With Target Sum: ทอยลูกเต๋าหาผลรวมเป้าหมาย

โจทย์

มีลูกเต๋า d ลูก แต่ละลูกมีหน้า f หน้า (เลข 1 ถึง f) หาจำนวนวิธีทอยให้ผลรวมเท่ากับ target modulo 10^9 + 7

ตัวอย่าง: d=2, f=6, target=7 → 6 วิธี (1+6, 2+5, 3+4, 4+3, 5+2, 6+1)

Dynamic Programming (Bottom-up)

dp[i][s] = จำนวนวิธีทอย i ลูกให้ได้ผลรวม s

  • Base: dp[1][face] = 1 สำหรับ face = 1..f
  • Transition: dp[i][s] = sum(dp[i-1][s-face] for face in 1..f if s-face > 0)
  • Answer: dp[d][target] % MOD

การติดตั้ง (Python Implementation)


class Solution:
    def numRollsToTarget(self, d: int, f: int, target: int) -> int:
        MOD = 10**9 + 7
        
        # dp[i][s] = ways to get sum s with i dice
        dp = [[0] * (target + 1) for _ in range(d + 1)]
        
        # Base case: 1 die
        for face in range(1, f + 1):
            if face <= target:
                dp[1][face] = 1
        
        # Fill DP table
        for i in range(2, d + 1):
            for s in range(i, target + 1):  # min sum = i, max = i*f
                for face in range(1, f + 1):
                    if s - face > 0:
                        dp[i][s] = (dp[i][s] + dp[i-1][s-face]) % MOD
        
        return dp[d][target]

# ทดสอบ
ob = Solution()
print(ob.numRollsToTarget(2, 6, 7))   # 6
print(ob.numRollsToTarget(1, 6, 3))   # 1
print(ob.numRollsToTarget(30, 30, 500))  # Large test

Output

6
1
... (large number modulo 1e9+7)

Space Optimization: 1D DP

เนื่องจาก dp[i] ขึ้นอยู่กับ dp[i-1] เท่านั้น สามารถลดเหลือ 1 array ได้:


def numRollsToTarget_optimized(self, d: int, f: int, target: int) -> int:
    MOD = 10**9 + 7
    dp = [0] * (target + 1)
    
    # Base case
    for face in range(1, f + 1):
        if face <= target:
            dp[face] = 1
    
    # Iterate dice
    for _ in range(2, d + 1):
        new_dp = [0] * (target + 1)
        for s in range(1, target + 1):
            if dp[s] == 0:
                continue
            for face in range(1, f + 1):
                if s + face <= target:
                    new_dp[s + face] = (new_dp[s + face] + dp[s]) % MOD
        dp = new_dp
    
    return dp[target]

Complexity

  • Time: O(d × target × f)
  • Space: O(target) (optimized) หรือ O(d × target) (2D)

สรุป

เป็นโจทย์ DP คลาสสิก (Dice Roll / Coin Change variant) จุดสำคัญคือการกำหนด state และ transition ให้ถูกต้อง รวมถึง modulo ในแต่ละขั้นตอนเพื่อป้องกัน overflow


หากมีข้อสงสัย สามารถถามได้ในส่วนความคิดเห็นครับ