題目描述
小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;
}