Leetcode第877题 石子游戏

一开始我想的是用每次都取最大值,不考虑下一次的情况。结果到第21个案例就通不过了
[3,7,2,3];也就是两段大小相等的时候。看来还是要动态规划去做。
还是区间做法,但是有点复杂,因为(i,j)和(i,j-2)、(i+2,j)、(i+1,j-1)都有关。

class Solution {
    
    
public:
    bool stoneGame(vector<int>& piles) {
    
    
        int n=piles.size();
        if(n<3) return true;
        int res=0;
        for(int p:piles) res+=p;
        int dp[n][n];
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n-1;++i) dp[i][i+1]=max(piles[i],piles[i+1]);
        for(int i=n-4;i>=0;i=i-2)
            for(int j=i+3;j<n;j=j+2)
                dp[i][j]=max(
                max(dp[i][j-2]+max(piles[j],piles[j-1]),dp[i+2][j]+max(piles[i],piles[i+1])),
                dp[i+1][j-1]+max(piles[i],piles[j])
                );
        return dp[0][n-1]>res/2;
    }
};

实际上这是个先手必胜的游戏!
自己还是蠢,因为实际上先手的人可以控制两个人的结果,因为堆数n必然是偶数个,所以如果先手的人第一下那的是第0队,那么下一个只能拿1或n-1,也就是奇数堆,而先手的再拿的时候,肯定可以继续拿偶数堆。同样的道理如果先手拿了奇数堆,那么空出来的两端必然为偶数堆,后手的人拿完后,先手的只要再继续拿奇数堆即可。
而总石头个数必然为奇数,所以先手的人只要算下奇数堆和还是偶数堆和哪个最大,拿哪个就好了

猜你喜欢

转载自blog.csdn.net/meixingshi/article/details/113926264