洛谷 P1430 序列取数

84 篇文章 2 订阅

题面

题意

给出一个序列,两人轮流从一端开始取任意个数,最后所取数的和即为得分,两人都想要较高得分,则先去者的最高得分是多少。

做法

首先不难想到用dp[i][j]表示序列剩下从i到j这段时的最高得分,这样的话有n^2种状态,n的状态转移,总复杂度为n^3,会T。
因此可以考虑记录下述值:
le[i][j]表示从左边开始取,剩下的数取到的最高分的最小值,也就是说:
le[i][j]=min(dp[i+1][j],dp[i+2][j],……+dp[j][j])
因此,le[i][j]=min(le[i+1][j],dp[i][j]).
ri[i][j]也同理。
只要枚举长度然后递推即可。

代码

#include<iostream>
#include<cstdio>
#define ll long long
#define N 1010
using namespace std;

ll T,n,num[N],dp[N][N],le[N][N],ri[N][N],qz[N];

int main()
{
    ll i,j,l;
    cin>>T;
    while(T--)
    {
        scanf("%lld",&n);
        qz[0]=0;
        for(i=1;i<=n;i++)
        {
            scanf("%lld",&num[i]);
            dp[i][i]=le[i][i]=ri[i][i]=num[i];
            qz[i]=qz[i-1]+num[i];
        }
        for(l=1;l<=n;l++)
        {
            for(i=1,j=l;j<=n;i++,j++)
            {
                dp[i][j]=qz[j]-qz[i-1]-min(le[i+1][j],ri[i][j-1]);
                le[i][j]=min(le[i+1][j],dp[i][j]);
                ri[i][j]=min(ri[i][j-1],dp[i][j]);
            }
        }
        printf("%lld\n",dp[1][n]);
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值