[LightOJ 1031]Easy Game[DP]

来源:互联网 发布:淘宝平台服务协议 编辑:程序博客网 时间:2024/04/30 10:37
题目链接:[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;}


0 0