[洛谷p2858] 奶牛零食

题目链接:

点我

题目分析:

这是什么,区间dp吗?怎么大佬都在说区间dp的样子
完蛋区间dp都不知道是啥quq
于是使用了玄学的姿势A过了这道题

dp[i][j][0]表示第i天,左边选了j个,当前选择了左边的最大价值方案,dp[i][j][1]表示从右边选
(其实第三维好像不用,但我还是记录了一下……这个思路和洛谷题解里面有一篇差不多,那个就是没记左右的,可以去看一下)
那么很容易得到状态转移方程:

(其中a是题目所给数组)
最后ans=max(f[n][i][0],f[n][i][1])(0<=i<=n)

注意第二维要从0开始枚举,因为有可能最开始就取右边的


代码如下:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int cnt=0,f=1;char c;
    c=getchar();
    while(!isdigit(c)){
        if(c=='-')f=-f;
        c=getchar();
    }
    while(isdigit(c)){
        cnt=cnt*10+c-'0';
        c=getchar();
    }
    return cnt*f;
}
int n,a[2005];
int f[2005][2005][2];
int main(){
    n=read();
    for(register int i=1;i<=n;i++)a[i]=read();
    f[1][1][0]=a[1];
    f[1][0][1]=a[n];
    f[1][0][0]=0;
    f[1][1][1]=0;
    for(register int i=1;i<=n;i++)
        for(register int j=0;j<=i;j++){
            f[i][j][0]=max(f[i-1][j-1][0],f[i-1][j-1][1])+a[j]*i;
            f[i][j][1]=max(f[i-1][j][0],f[i-1][j][1])+a[n-i+j+1]*i;
        }
    int ans=-1;
    for(register int i=1;i<=n;i++){
        if(f[n][i][0]>ans)ans=f[n][i][0];
        if(f[n][i][1]>ans)ans=f[n][i][1];
    }
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/kma093/p/10297603.html
今日推荐