395 硬幣排成線 II

2022-02-14 21:23:30 字數 3119 閱讀 3606

中文english

n個不同價值的硬幣排成一條線。兩個參賽者輪流從 左邊 依次拿走 1 或 2 個硬幣,直到沒有硬幣為止。計算兩個人分別拿到的硬幣總價值,價值高的人獲勝。

請判定 先手玩家 必勝還是必敗?

若必勝, 返回true, 否則返回false.

樣例 1:

輸入: [1, 2, 2]

輸出: true

解釋: 先手玩家直接拿走兩顆硬幣即可.

樣例 2:

輸入: [1, 2, 4]

輸出: false

解釋: 無論先手拿乙個還是兩個, 後手可以拿完, 然後總價值更高.

輸入測試資料 (每行乙個引數)如何理解測試資料?

解法一:動態規劃

dp[i]代表的是倒數n-i個,逆著算,例如dp[length - 2] = values[length - 2] + values[length - 1] ,表示的是i到length - 1可以拿到的最大值

class

solution:

"""@param values: a vector of integers

@return: a boolean which equals to

true

ifthe first player will win

"""def firstwillwin(self, values):

# write your code here

#動態規劃

#如果是len(values)

<=3的情況,則直接給出答案

#如果是len(valeus) >3的情況,分情況,要麼先手拿乙個,要麼拿兩個

length =len(values)

if (length <= 2): return

true

dp = [0

for _ in range(length + 1

)] total = 0

#如果是

<=3的話

#如果是只拿最後乙個的話,先手必拿

dp[length - 1] = values[length - 1

] #如果是剩餘最後兩個的話,先手也必拿

dp[length - 2] = values[length - 1] + values[length - 2

] #如果是剩餘三個的話,那麼先手最優策略是拿前兩個,最後乙個留給後手

dp[length - 3] = values[length - 2] + values[length - 3

]

total = sum(values[length - 3

:]) #如果是大於3的話,分情況考慮

for i in range(length - 4, -1, -1

): total +=values[i]

#先手要麼拿乙個,要麼拿兩個,後手也是最優策略,所以後手也盡可能的多拿,min(dp[i + 2], dp[i + 3

]) dp[i] = max(values[i] + min(dp[i + 2], dp[i + 3]), values[i] + values[i + 1] + min(dp[i + 3], dp[i + 4

]))

#最後比較兩者大小,肯定是先手拿,也就是第乙個

return dp[0] > total - dp[0

]

中文english

n個硬幣排成一條線。兩個參賽者輪流從右邊依次拿走 1 或 2 個硬幣,直到沒有硬幣為止。拿到最後一枚硬幣的人獲勝。

請判定 先手玩家 必勝還是必敗?

若必勝, 返回true, 否則返回false.

樣例 1:

輸入: 1

輸出: true

樣例 2:

輸入: 4

輸出: true

解釋:

先手玩家第一輪拿走乙個硬幣, 此時還剩三個.

這時無論後手玩家拿乙個還是兩個, 下一次先手玩家都可以把剩下的硬幣拿完.

o(1) 時間複雜度且o(1) 儲存。

輸入測試資料 (每行乙個引數)如何理解測試資料?

解法:動態規劃

class

solution:

"""@param n: an integer

@return: a boolean which equals to

true

ifthe first player will win

"""def firstwillwin(self, n):

# write your code here

#當前必勝和必敗由前面兩個決定

#只考慮先手,and表示的是後手的最優策略,只要有前面先手有乙個為false,那麼後手一定是true

#dp[i] = dp[i - 2] and dp[i - 3] or dp[i - 3] and dp[i - 4

] #當前先手 =取乙個後手的最優策略 取兩個後手的最優策略(所以中間是and,表示,只要之前先手乙個為false,此時後手採取最優策略,一定為true)

if not n: return

false

if n <= 2: return

true

dp = [false for _ in range(n + 1

)] #前面三個的話,是固定

dp[1] =true

dp[2] =true

dp[3] =false

for i in range(4, n + 1

): dp[i] = (dp[i - 2] and dp[i - 3]) or (dp[i - 3] and dp[i - 4

])

return

dp[n]

硬幣排成線

題目 有 n 個硬幣排成一條線。兩個參賽者輪流從右邊依次拿走 1 或 2 個硬幣,直到沒有硬幣為止。拿到最後一枚硬幣的人獲勝。請判定 先手玩家 必勝還是必敗?若必勝,返回 true,否則返回 false.樣例樣例 1 輸入 1 輸出 true 樣例 2 輸入 4 輸出 true 解釋 先手玩家第一輪...

lintcode 硬幣排成線

有 n 個硬幣排成一條線。兩個參賽者輪流從右邊依次拿走 1 或 2 個硬幣,直到沒有硬幣為止。拿到最後一枚硬幣的人獲勝。請判定 先手玩家 必勝還是必敗?若必勝,返回 true,否則返回 false.輸入 4 輸出 true 解釋 先手玩家第一輪拿走乙個硬幣,此時還剩三個.這時無論後手玩家拿乙個還是兩...

lintcode 硬幣排成線2

有 n 個不同價值的硬幣排成一條線。兩個參賽者輪流從 左邊 依次拿走 1 或 2 個硬幣,直到沒有硬幣為止。計算兩個人分別拿到的硬幣總價值,價值高的人獲勝。請判定 先手玩家 必勝還是必敗?若必勝,返回 true,否則返回 false.樣例 1 輸入 1,2,2 輸出 true 解釋 先手玩家直接拿走...