算法60---石子游戲/傳球游戲【動態規划】


一、題目:

亞歷克斯和李用幾堆石子在做游戲。偶數堆石子排成一行,每堆都有正整數顆石子 piles[i] 。

游戲以誰手中的石子最多來決出勝負。石子的總數是奇數,所以沒有平局。

亞歷克斯和李輪流進行,亞歷克斯先開始。 每回合,玩家從行的開始或結束處取走整堆石頭。 這種情況一直持續到沒有更多的石子堆為止,此時手中石子最多的玩家獲勝。

假設亞歷克斯和李都發揮出最佳水平,當亞歷克斯贏得比賽時返回 true ,當李贏得比賽時返回 false 。

 

示例:

輸入:[5,3,4,5]
輸出:true
解釋:
亞歷克斯先開始,只能拿前 5 顆或后 5 顆石子 。
假設他取了前 5 顆,這一行就變成了 [3,4,5] 。
如果李拿走前 3 顆,那么剩下的是 [4,5],亞歷克斯拿走后 5 顆贏得 10 分。
如果李拿走后 5 顆,那么剩下的是 [3,4],亞歷克斯拿走后 4 顆贏得 9 分。
這表明,取前 5 顆石子對亞歷克斯來說是一個勝利的舉動,所以我們返回 true 。

 

提示:

  1. 2 <= piles.length <= 500
  2. piles.length 是偶數。
  3. 1 <= piles[i] <= 500
  4. sum(piles) 是奇數。

思路:動態規划:時間O(N^2),空間O(N^2)

  • dp[i][j]表示:表示在piles中下標 i 至下標 j 之間的玩家1 所拿石子總數和 玩家2所拿石子總數之差。dp[i][j] > 0 表明玩家1贏,輸出True
  • 子問題:dp[ i+1 ][ j ]和dp[ i ][ j-1 ]
  • 初始狀態:dp的初始狀態是 i = j 即只有一個石子堆,由於玩家1先拿,則 dp[ i ][ j ] = piles[ i ]
  • 狀態方程:

dp[ i ][ j ] = max( piles[ i ] - dp[ i+1 ][ j ], piles[ j ] - dp[ i ][ j-1 ])

【解釋:當玩家1拿了最左邊下標為 i 的石子后,玩家1和玩家2的石子數之差為 piles[ i ] - dp[ i+1 ][ j ], 當玩家1拿了最右邊下標為j的那堆石子后,玩家1和玩家2的石子數之差為 piles[ j ] - dp[ i ][ j-1 ], 取其中較大者為新的最優解。】

 

代碼:

def stronegame(piles):
    n = len(piles)
    dp = [[0] * n for i in range(n)]
    for i in range(n):
        dp[i][i] = piles[i]
    for i in range(n-2,-1,-1):
        for j in range(i+1,n):
            dp[i][j] = max(piles[i]-dp[i+1][j],piles[j]-dp[i][j-1])
    return dp[0][-1] > 0
piles = [5,3,4,5]
stronegame(piles)

 二、題目:傳球游戲

k個猿輔導老師,傳一個球,傳n次,球從A老師手里開始傳,又傳回A老師手里的傳球方式有多少種?(每次可以傳給除自己外的任何一個人)比如輸入k=3,n=3,那么輸出為2。只有二種傳球方式:abca,acba


這個題,遞推即可,每一個傳球,只有兩種可能,一種球在A老師手里,一種球不在A老師手里
令dp[n][0]表示球在A老師手里的方案數,令dp[n][1]表示球不在A老師手里的方案數,於是
dp[n+1][0]=dp[n][1]
dp[n+1][1]=dp[n][0]*k+dp[n][1]*(k-1)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM