877. Stone Game 石子游戏

877. Stone Game 石子游戏

题目描述 Alex 先拿,石子总数为奇数,每次只能拿前或后,两个人都做最优的选择,谁的石子数多谁赢,Alex 赢返回 true

定义二维数组 dp[i][j] 表示下标 i至j的元素区间先拿的人和后拿的人分别能够得到的最大石子数

状态方程: dp[i][j].first=max(piles[i]+dp[i+1][j].second, piles[j]+dp[i][j-1].second) dp[i][j].second=去除被选择的元素( i 或 j )的间隔元素后先拿人的最多石子数

bool stoneGame(vector<int>& piles) {
    int len=piles.size();
    vector<vector<pair<int, int>> > dp(piles.size(), vector<pair<int, int> >(len, make_pair(0,0)));
    for(int i=0;i<len;++i) {
        dp[i][i].first=piles[i];
    }

    for(int i=len-2;i>=0;--i) {
        for(int j=i+1;j<len;++j) {
            if (piles[i]+dp[i+1][j].second > piles[j]+dp[i][j-1].second) {
                dp[i][j].first=piles[i]+dp[i+1][j].second;
                dp[i][j].second=dp[i+1][j].first;
            } else {
                dp[i][j].first=piles[j]+dp[i][j-1].second;
                dp[i][j].second=dp[i][j-1].first;
            }
        }
    }

    return dp[0][len-1].first > dp[0][len-1].second;
}

状态压缩后的版本

bool stoneGame(vector<int>& piles) {
    int len=piles.size();
    vector<pair<int, int> > dp(piles.size(), make_pair(0,0));
    for(int i=0;i<len;++i)
        dp[i].first=piles[i];

    for(int i=len-2;i>=0;--i) {
        for(int j=i+1;j<len;++j) {
            int c1=piles[i]+dp[j].second;
            int c2=piles[j]+dp[j-1].second;
            if (c1 > c2) {
                dp[j].second=dp[j].first;
                dp[j].first=c1;
            } else {
                dp[j].second=dp[j-1].first;
                dp[j].first=c2;
            }
        }
    }

    return dp[len-1].first > dp[len-1].second;
}

#DP