题目链接:
[LightOJ 1031]Easy Game[DP]
题意分析:
A和B玩游戏,A先手。规则为:每轮,每人至少从左边开始或者从右边开始取1个数字以上,取的数字之和即为这个人得到的分数。现在问:在两人都采取最优策略的情况下,A和B的差值最大为多少?
解题思路:
定义:dp[i][j]为,拿完区间为[i,j]时,A能取到的最大分值,那么最终答案就是dp[1][n] - (sum - dp[1][n])。sum为数列的所有之和。
怎么转移呢?因为dp[i][j] = max(s - dp[i + k][j], s - dp[i][j - k]) (k:1 ~ j - i)
个人感受:
呼,又加深了理解啊。本来还在想,怎么可能最优局面优就能达到最终局面优,然后舍友一语道破:因为你已经比较了所有状态。赞赞赞~
具体代码如下:
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<string>
#define ll long long
#define pr(x) cout << #x << " = " << (x) << '\n';
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 111;
int dp[MAXN][MAXN];
int a[MAXN], sum[MAXN];
int dfs(int l, int r) {
int &ret = dp[l][r];
if (ret > -INF) return ret;
if (l == r) return ret = a[l];
int s = sum[r] - sum[l - 1];
ret = s; // 全拿的情况
for (int i = 1; i <= r - l; ++i)
ret = max(s - dfs(l + i, r), max(ret, s - dfs(l, r - i)));
return ret;
}
int main()
{
int kase, n; cin >> kase;
for (int cas = 1; cas <= kase; ++cas) {
cout << "Case " << cas << ": ";
cin >> n;
sum[0] = 0;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
sum[i] = sum[i - 1] + a[i];
}
for (int i = 1; i <= n; ++i)
for (int j = i; j <= n; ++j)
dp[i][j] = -INF;
cout << 2 * dfs(1, n) - sum[n] << '\n';
}
return 0;
}