uva10891 - Game of Sum

题意:
给一个序列,AB两人比赛,每人每次只能从左或从右取任意连续数,都足够聪明,极力想让自己赢,A先开始取,让你求A和B都取最优策略时,A-B的得分结果。
思路:
初写dp没多久,式子怎么也推不出来,看了题解,原来是这样的:
让sum[i]表示前i个数总和,要求A-B即求 A - (sum[n]- A),即求2*A-sum[n]。
求A的话,让dp[i][j]表示A在第i~j个数中取到的值,则dp[1][n]即为最终要求得的A,有dp[i][j]=(sum[j]-sum[i-1]) - 区间i~j的最小值(m).

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 105;
int arr[N],sum[N],dp[N][N],visit[N][N],n;

int dfs(int i,int j) {
    if (visit[i][j])
        return dp[i][j];
    visit[i][j] = 1;
    int k, m = 0;
    for (k = i + 1; k <= j; k++)
        m = min(m, dfs(k, j));
    for (k = i; k < j; k++)
        m = min(m, dfs(i, k));
    dp[i][j] = sum[j] - sum[i - 1] - m;
    return dp[i][j];

}

int main() {
    int n;
    while (~scanf("%d", &n) && n) {
        int i;
        memset(visit, 0, sizeof(visit));
        for (i = 1; i <= n; i++) {
            scanf("%d", &arr[i]);
            sum[i] = sum[i - 1] + arr[i];
        }
        printf("%d\n", 2 * dfs(1, n) - sum[n]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值