線性dp [USACO3.3]遊戲 A Game(洛谷 P2734)

[USACO3.3]遊戲 A Game

題目背景

有如下一個雙人遊戲:N(2 <= N <= 100)個正整數的序列放在一個遊戲平臺上,遊戲由玩家1開始,兩人輪流從序列的任意一端取一個數,取數後該數字被去掉並累加到本玩家的得分中,當數取盡時,遊戲結束。以最終得分多者爲勝。

題目描述

編一個執行最優策略的程序,最優策略就是使玩家在與最好的對手對弈時,能得到的在當前情況下最大的可能的總分的策略。你的程序要始終爲第二位玩家執行最優策略。


題目看上去像博弈論的題目,但是其實不是,是一道線性dp題,轉移方程比較難想;

dp[l][r] 表示區間 [l,r] 玩家能獲得的最大分數,那麼: dp[l][r]=sum[l,r]-min(dp[l+1][r],dp[l][r-1]);

運用到了一點貪心思維,dp[l+1][r]和dp[l][r-1]分別表示另一個玩家在該玩家拿完後的最大分數;減去它們的最小值,不就是該玩家能獲得的最大分數嗎?

代碼:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,LL>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=1100;
const int M=50100;
const int mod=1e9;
int n,dp[N][N],sum[N],a[N];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i],sum[i]=sum[i-1]+a[i];	
	for(int i=1;i<=n;i++) dp[i][i]=a[i];
	for(int len=2;len<=n;len++){
		for(int i=1;i+len-1<=n;i++){
			int j=i+len-1;
			dp[i][j]=sum[j]-sum[i-1]-min(dp[i+1][j],dp[i][j-1]);
		}
	}
	cout<<dp[1][n]<<" "<<sum[n]-dp[1][n]<<endl;
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章