码迷,mamicode.com
首页 > 其他好文 > 详细

喵哈哈村的挑衅

时间:2015-07-28 23:17:29      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:有两排物品,每排都有n个,青君和狗哥轮流从每排的两侧拿任意一个物品。青君先手,假设狗哥绝顶聪明,青君所拿物品价值之和最大为多少?
分析:区间DP。
状态:dp[x1][y1][x2][y2],表示在区间[x1, y1]和区间[x2, y2]中能取到的最大值。
状态转移方程:有四种情况,分别为x1+1,y1-1,x2+1,y2-1。显然取四个中最小的那个。
下面的代码里,分别用a,b数组来表示两排的前缀和。

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

int n, A[30], B[30];
int d[30][30][30][30], v[30][30][30][30];

int DP(int L1, int R1, int L2, int R2) {
    if (v[L1][R1][L2][R2])
        return d[L1][R1][L2][R2];
    v[L1][R1][L2][R2] = 1;

    int sum = 0, ans = 0;
    if (L1 <= R1)
        sum += A[R1] - A[L1-1];
    if (L2 <= R2)
        sum += B[R2] - B[L2-1];

    if (L1 <= R1) {
        ans = max(ans, sum - DP(L1+1, R1, L2, R2));
        ans = max(ans, sum - DP(L1, R1-1, L2, R2));
    }
    if (L2 <= R2) {
        ans = max(ans, sum - DP(L1, R1, L2+1, R2));
        ans = max(ans, sum - DP(L1, R1, L2, R2-1));
    }

    return d[L1][R1][L2][R2] = ans;
}

int main() {
    while (scanf("%d", &n) != EOF) {
        memset(d, 0, sizeof(d));
        memset(v, 0, sizeof(v));
        for (int i = 1; i <= n; i++) {
            int tmp;
            scanf("%d", &tmp);
            A[i] = A[i-1] + tmp;
        }
        for (int i = 1; i <= n; i++) {
            int tmp;
            scanf("%d", &tmp);
            B[i] = B[i-1] + tmp;
        }

        printf("%d\n", DP(1, n, 1, n));
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

喵哈哈村的挑衅

标签:

原文地址:http://blog.csdn.net/kl28978113/article/details/47112133

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!