题目描述
考虑一个由两个玩家玩的游戏。游戏开始前给定一串排成一排的N个数字。两位玩家轮流从这一串数中的最左端或者最右端取出一个数。当所有数字都被取完后,游戏结束。此时,两位玩家各自的得分将是他所有取出的数的和。得分较高的玩家获胜。
假设你是先取者。请编写程序制定一个游戏的最佳策略。最佳策略是指这样一种数字取法,它能在最坏的情况(后取者的策略对自己最不利的情况)下得到最高的得分。
输入格式
第一行,一个正整数N,输入数据保证1≤N≤100。
第二行,从左至右给出了游戏初始时的N个正整数。这 些正整数保证不超过200。
输出格式
一行,输出两个用空格隔开的正整数。他们分别表示游戏的先取者在最坏情况下最高的得分和此时后取者的得分。
输入样例
6
4 7 2 9 5 2
输出样例
18 11
题解
当剩下$[i, j]$时,先手可以控制对方拿$[i + 1, j]$还是$[i, j - 1]$,根据这个思路dp即可。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <iostream> #define MAX_N 101 using namespace std; int n; int a[MAX_N]; int f[MAX_N][MAX_N]; int main() { cin >> n; for(register int i = 1; i <= n; ++i) { cin >> a[i]; f[i][i] = a[i]; a[i] += a[i - 1]; } for(register int i = n - 1; i >= 1; --i) { for(register int j = i + 1; j <= n; ++j) { f[i][j] = a[j] - a[i - 1] - min(f[i + 1][j], f[i][j - 1]); // 自己可以操纵对方拿什么 } } cout << f[1][n] << ' ' << a[n] - f[1][n]; return 0; }