由取數遊戲談一談博弈問題的dp解法

題目描述

小C和小Q在玩一個取數字的遊戲,給定一串數列,兩個人依次從數列的頭部或者尾部取走一個數,把每個人取到的數字相加,誰大就誰贏了。現在小C請你幫他算算,如果他們兩個人都從最優的角度考慮,最終他們的得分是多少?

輸入

輸入第一行, 一個整數n,表示數列的長度;

接下來一行有n個數,表示數列中的每個元素。

輸出

輸出最終的得分(小C每次都讓小Q先取)。

樣例輸入

4
1 3 2 4

樣例輸出

3 7

這是一道典型的博弈問題,關鍵在於,“最優”二字,這也是本題最玄學的地方,小C和小Q都非常聰明,“聰明”很難定義,第一印象可能會貪心的把他當作一道模擬題。雖然也能騙點分數,但顯然不是正解。

對於博弈問題,我們要緊緊抓住最優二字,定義狀態的時候也要抓住,所以我們可以定義dp[L][R]爲當前選手在L,R這一區間內的最優情況,很顯然我們不難寫出狀態轉移方程

dp[L][R]=sum[L][R]-min(dp[L+1][R],dp[L][R-1])

這裏的min代表對手也很聰明的情況下,他的最差情況。

不難寫出記憶化搜索

#include<bits/stdc++.h>
using namespace std;
int n;
int A[5005],sum[5005];
int dp[5005][5005];
int solve(int L,int R){
    if(dp[L][R]>0)return dp[L][R];
    return dp[L][R]=sum[R]-sum[L-1]-min(solve(L+1,R),solve(L,R-1));
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        scanf("%d",&A[i]);
        dp[i][i]=A[i];
        sum[i]=sum[i-1]+A[i];
    }
    int ans=solve(1,n);
    printf("%d %d",sum[n]-ans,ans);
    return 0;
}       
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章