HDU 6199 dp

题意:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6199
AB两个人玩游戏,n个数,从左到右依次选取。第一个人可以选择1个或者2个数,假设某一轮一个人选择了k个数,那么下一轮另一个人就要选择k个或者k+1个数,如果剩下的数字不够就不能选择,游戏终止。此时比较A-B的大小,问两个人都采取最优策略,都尽可能让自己所获得的数的总和大,最后A-B的最大值是多少。


思路:

真的菜,网络赛时候有正确思路,结果细节没搞清楚,最后愣是没调出来。
dp[i][j][0/1]表示当前这一轮是0(A)或1(B)选择数字,还剩下j个数,马上将要选择i个数的A-B的最大值。然后从后往前倒着推,最后答案就是max(dp[1][n][0], dp[2][n][0])。
状态转移方程为:
dp[i][j][0] = min(dp[i][j-i][1], dp[i+1][j-i][1])+val;
dp[i][j][1] = max(dp[i][j-i][0], dp[i+1][j-i][0])+val;
其中,val为选择的i个数的总和,这里有一点一定要注意,0对应min,而1对应max,不能搞反。因为这是从后往前倒推的,当前是0面对的一定是之前的1所留下来对1最好的局面,也就是min。
恶心的爆内存,要改成滚动数组。
还要注意很多细节问题,详见代码。


代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 2e9 + 1;
const int MAXN = 2e4 + 10;

int a[MAXN], sum[MAXN], dp[2][MAXN][2];

int main() {
    //freopen("in.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while (T--) {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            sum[i] = sum[i - 1] + a[i];
        }
        if (n == 1) {
            printf("%d\n", a[1]);
            continue;
        }
        for (int i = 199; i >= 1; i--) {
            for (int j = i; j <= n; j++) {
                int l = n - j, r = n - j + i;
                if (j - i < i) {
                    dp[i % 2][j][0] = sum[r] - sum[l];
                    dp[i % 2][j][1] = -(sum[r] - sum[l]);
                }
                else {
                    dp[i % 2][j][0] = dp[i % 2][j - i][1] + sum[r] - sum[l];
                    dp[i % 2][j][1] = dp[i % 2][j - i][0] - (sum[r] - sum[l]);
                    if (i + 1 <= 199 && j - i >= i + 1) {
                        dp[i % 2][j][0] = min(dp[i % 2][j][0], dp[(i + 1) % 2][j - i][1] + sum[r] - sum[l]);
                        dp[i % 2][j][1] = max(dp[i % 2][j][1], dp[(i + 1) % 2][j - i][0] - (sum[r] - sum[l]));
                    }
                }
            }
        }
        int ans = max(dp[0][n][0], dp[1][n][0]);
        printf("%d\n", ans);
    }
    return 0;
}
发布了255 篇原创文章 · 获赞 29 · 访问量 10万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章