leetcode877

题目链接

 

这道题目的限制条件是比较trick的,它说了是偶数个数字,所以其实先手必胜。因为先手者可以计算编号是奇数的堆的和以及编号是偶数的堆的和,然后比较,如果奇数堆和大的话,那就先选择第一个,然后保持选择奇数堆即可。如果是偶数堆和较大的话,那么先选择最后一个堆,然后保持选择偶数堆即可。

但是更一般的来说,我们用动态规划来解决这个问题,用dp[i][j]表示piles[i]-piles[j]之间先手可以赢后手的分数,并且此时先手取的是i或者j。那么最后的结果就是看dp[0][n-1](n是piles的长度),因为0和n-1就是先手可以进行选择的目标。

对于某个范围dp[i][j]来说,如果先手取i,那么dp[i][j] = piles[i]-dp[i+1][j],因为piles[i+1]~piles[j]是后手赢先手的分数,所以此时先手选择piles[i]和它做差;当然先手也可以取j,那么dp[i][j] = piles[j]-dp[i][j-1]。最后就是取这两者的极大值,即 dp[i][j] = max(piles[i]-dp[i+1][j], piles[j]-dp[i][j-1])。可以看出是一个区间的DP。

 

 1 class Solution {
 2 public:
 3     bool stoneGame(vector<int>& piles) {
 4         int n = (int)piles.size();
 5         vector<vector<int>> dp(n+1, vector<int>(n+1, 0));
 6         for(int i=0;i<n;i++) dp[i][i] = piles[i];
 7         for(int l=1;l<n;l++){
 8             for(int i=0;i+l<n;i++){
 9                 dp[i][i+l] = max(piles[i]-dp[i+1][i+l], piles[i+l]-dp[i][i+l-1]);
10             }
11         }
12         return (dp[0][n-1]>0);
13     }
14 };

 

posted @ 2018-08-27 14:00  leohujx  阅读(716)  评论(0)    收藏  举报