1. 程式人生 > 其它 >洛谷 P2734 [USACO3.3]遊戲 A Game

洛谷 P2734 [USACO3.3]遊戲 A Game

洛谷 P2734 [USACO3.3]遊戲 A Game

Description

原題連結

Solution

今天集訓講了博弈論,於是在洛谷發現了這道題,但是並不知道為什麼有博弈論的標籤QWQ。

這明明是道 \(區間dp\) 好不好啊喂。

一道比較基礎的區間 \(dp\)

我們設 \(f[i][j]\) 表示取完 \(i\) ~ \(j\) 之間的物品,先手能獲得的最大分數。

那麼後手得分就是 \(n - f[i][j]\)

注意到兩人只能從兩邊取,那麼我們轉移就更簡單了,連斷點都不需要列舉。

先手可能取 \(i\),也可能取 \(j\)

轉移方程: $f[i][j] = max((sum[j] - sum[i - 1]) - f[i + 1][j] + a[i], (sum[j] - sum[i - 1]) - f[i][j - 1] + a[j]) $

這裡的 \(a[i]\)\(a[j]\) 可以在輸入時,當作初始值賦進去。

\(sum[i]:\) 字首和,表示 1 ~ \(i\) 物品的數字和。

Code

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 110;
int n;
int a, f[N][N], sum[N];

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; i++){
		scanf("%d", &a);
		sum[i] = sum[i - 1] + a;
		f[i][i] = a;
	}
	for(int len = 2; len <= n; len++)
	 	for(int i = 1; i + len - 1 <= n; i++){
	 		int j = i + len - 1;
	 		f[i][j] = max((sum[j] - sum[i - 1]) - f[i + 1][j], (sum[j] - sum[i - 1]) - f[i][j - 1]);
	 	}
	printf("%d %d\n", f[1][n], sum[n] - f[1][n]);
	return 0;
}

End