[LintCode] Coins in a Line II


There are n coins with different value in a line. Two players take turns to take one or two coins from left side until there are no more coins left. The player who take the coins with the most value wins.

Could you please decide the first player will win or lose?

Example

Given values array A = [1,2,2], return true.

Given A = [1,2,4], return false.

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

請判定 第一個玩家 是輸還是贏?

樣例

給定數組 A = [1,2,2], 返回 true.

給定數組 A = [1,2,4], 返回 false.

http://www.lintcode.com/en/problem/coins-in-a-line-ii/

 

貪心法,對於雙方玩家都先取一枚硬幣,在決定要不要取第二枚硬幣時,比較第二枚硬幣和第二枚硬幣之后的一枚硬幣的大小,即values[i]與values[i+1]的大小,如果values[i]大,就取走,否則就留下。

下面是AC代碼。至於正確性的證明,唔,讓我先想一想,想明白了再回來補上~

 1 class Solution {
 2 public:
 3     /**
 4      * @param values: a vector of integers
 5      * @return: a boolean which equals to true if the first player will win
 6      */
 7     bool firstWillWin(vector<int> &values) {
 8         // write your code here
 9         int val1 = 0, val2 = 0;
10         bool turn = true;
11         for (int i = 0; i < values.size(); ) {
12             int &val = turn ? val1 : val2;
13             val += values[i++];
14             if (i < values.size() && (i + 1 >= values.size() || values[i] >= values[i + 1])) {
15                 val += values[i++];
16             }
17             turn = !turn;
18         }
19         return val1 > val2;
20     }
21 };

上面的貪心應該不對,下面的dp肯定是正確的。dp[idx]表示從第idx個硬幣到最后一個硬幣所能拿到的最大value,因為對手也取最優策略,所以每次取完后要對手會留給我們兩種方案,我們只能取價值更小的一種方案。

 1 class Solution {
 2 public:
 3     /**
 4      * @param values: a vector of integers
 5      * @return: a boolean which equals to true if the first player will win
 6      */
 7     bool firstWillWin(vector<int> &values) {
 8         // write your code here
 9         int n = values.size();
10         vector<int> dp(n + 1, -1);
11         int sum = 0;
12         for (auto v : values) sum += v;
13         return sum < 2 * dfs(dp, values, n);
14     }
15     int dfs(vector<int> &dp, vector<int> &values, int idx) {
16         if (dp[idx] != -1) return dp[idx];
17         int n = values.size();
18         if (idx == 0) {
19             dp[idx] = 0;
20         } else if (idx == 1) {
21             dp[idx] = values[n-1];
22         } else if (idx == 2) {
23             dp[idx] = values[n-1] + values[n-2];
24         } else if (idx == 3) {
25             dp[idx] = values[n-2] + values[n-3];
26         } else {
27             int take1 = min(dfs(dp, values, idx - 2), dfs(dp, values, idx - 3)) + values[n-idx];
28             int take2 = min(dfs(dp, values, idx - 3), dfs(dp, values, idx - 4)) + values[n- idx + 1] + values[n - idx];
29             dp[idx] = max(take1, take2);
30         }
31         return dp[idx];
32     }
33 };

 


免責聲明!

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



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