HNU-LTS buy wine(区间DP)
在一个阳光明媚的下午,ltslts的朋友来看他。所以他决定买些酒。
我们知道店里所有的酒都在同一个架子上,这些酒从左到右编号是1到n。
他们的朋友很有钱,所以他们会买所有的酒。但他的饮酒能力有限,所以他每天只买一瓶酒。
我们都知道,酒越久越值钱。
第一种情况下,第i瓶葡萄酒的价值为vi。在第t天,ltslts将在货架最左边或最右边购买一瓶葡萄酒,并得到值vi⋅t。
很明显,所有的酒都会在第n天被ltslts买走,他想知道他能得到的最大价值是多少。
例如,我们考虑n=5,葡萄酒的价值是{1,3,1,5,2}。
第一天,我们买了最左边的酒,得到了1个价值点,剩下的酒是{3,1,5,2}。
第二天,我们买了最右边的酒,得到了4个值点,剩下的酒是{3,1,5}。
第三天,我们买了最左边的酒,得到了9个价值点,剩下的酒是{1,5}。
第四天,我们买了最左边的酒,得到了4个价值点,剩下的酒是{5}。
最后一天,我们得到了25个价值点,我们总共得到了43个价值点。
输入
第一行包含单个整数n(1≤n≤2000),表示葡萄酒的数量。
在接下来的n行中,每行包含一个整数vi(1≤vi≤109),表示第i种葡萄酒的价值。
输出
在一行中打印单个整数:ltslts可以获得的最大值。
/* *author: zlc *zucc_acm_lab *just do it */ #include<bits/stdc++.h> using namespace std; typedef long long ll; const double pi=acos(-1.0); const double eps=1e-6; const int mod=1e9+7; const int inf=1e9; const int maxn=2e5+100; inline ll read () {ll x=0;ll f=1;char ch=getchar();while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;} ll qpow (ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} int n; ll a[maxn]; ll c[maxn]; ll ans=0; // 1 3 1 5 2 // 1+2*2+3*3+1*4+5*5 //dp[l][r]表示取到左下标为l,右下标为r的最大值 deque<int> q; ll dp[5005][5005]; int main () { n=read(); for (int i=1;i<=n;i++) a[i]=read(); ll tot=1; int l=1,r=n; for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) { dp[j][j+i-1]=max(dp[j+1][j+i-1]+a[j]*(n-i+1),dp[j][j+i-2]+a[j+i-1]*(n-i+1)); } } ans=dp[1][n]; printf("%lld\n",ans); }