USACO Section 3.3 A Game

28 篇文章 0 订阅

题意:

一串数字两个人轮流拿头或尾上的一个数字  求两个人都按最优情况行动最后得分分别是多少


思路:

非常经典的dp一定要会!!

dp[i][j]表示当前拿数字的人在[i,j]区间内能得到的最大得分

状态转移  dp[i][j] = sum[j] - sum[i-1] - min( dp[i+1][j] , dp[i][j-1] )

理解一下就是[i,j]区间的数字除去别人拿的就是我的得分

因为行动方案最优  那么我要找到转移到我现在要求的状态的“敌人最小得分”

通过“敌人最小得分”求出的我的得分一定是我最优的方案


代码:

/*
ID: housera1
PROG: game1
LANG: C++
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define M 205

int n;
int a[M],sum[M],dp[M][M];

int main(){
	int Debug=0;
	if(!Debug){
		freopen("game1.in","r",stdin);
		freopen("game1.out","w",stdout);
	}
	int i,j,tmp;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i];
        dp[i][i]=a[i];
    }
    for(i=1;i<n;i++)
    {
        for(j=1;j+i<=n;j++)
        {
            dp[j][i+j]=sum[i+j]-sum[j-1]-min(dp[j+1][i+j],dp[j][i+j-1]);
        }
    }
	printf("%d %d\n",dp[1][n],sum[n]-dp[1][n]);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值