[洛谷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;
}
posted @ 2019-01-21 10:48  kma_093  阅读(192)  评论(0编辑  收藏  举报