[LightOJ 1031]Easy Game[DP]

题目链接: [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;
}


你可能感兴趣的:(dp)