一、題目:
亞歷克斯和李用幾堆石子在做游戲。偶數堆石子排成一行,每堆都有正整數顆石子 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 。
提示:
2 <= piles.length <= 500
piles.length
是偶數。1 <= piles[i] <= 500
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)