Description
已知:这是一个 1×N 的花园,被分成了 N 个格子,每个格子里有一种神奇的樱花,看到第 i 个格子上的花,洋娃娃会得到满足度 Ci (每个花的满足度只被计算一次)。现在洋娃娃从任意格子走进花园,当然从第 i 个格子进去会消耗 Di 个单位的满足度,然后游历花园,在一个格子向右走需要耗费 R 个单位的满足度,向左走需要耗费 L 个单位的满足度,最后从第 i 个格子出花园又要耗费 Fi 个单位的满足度。
接下来,需要设计一套游历方案,使得最终获得的总满足度最高。
Input
第一行依次给出三个正整数N,L,R。 第二行有N个整数,第i个数为Di。 第三行有N个整数,第i个数为Fi。 第四行有N个整数,第i个数为Ci。
Output
仅需要输出一行包括一个整数,表示最大获得的满足度为多少。
Sample Input 1
5 1 1
1 1 1 1 1
1 1 1 1 1
1 1 3 1 1
Sample Output 1
1
Hint
对于30%数据,N<=10。
对于60%数据,N<=100。
对于100%数据,N<=1000,0<=L,R,D[i],F[i],C[i]<=1000000。
错误的贪心:枚举i,j,找从i进直接走到j出去的最大值。
错误原因:每个格子价值只计算一次,但是可以反复走,即可以先把一边的格子走过再回头从另一边出去。
所以要考虑从i进,先去完一边的格子,回头取完另一边的格子再走到j出去。
计算时可以先预处理,算出从i向左走和向右走再回到i能得到的最大值。

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<iostream>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define inf 1000000010
using namespace std;
const int maxn = 1005;
int max(int a,int b){return a>b?a:b;}
int n, lc, rc;
int D[maxn], F[maxn], C[maxn];
int l[maxn], r[maxn], q[maxn];
void data_in(){
scanf("%d%d%d", &n, &lc, &rc);
for(int i=1;i<=n;i++) scanf("%d", &D[i]);
for(int i=1;i<=n;i++) scanf("%d", &F[i]);
for(int i=1;i<=n;i++) scanf("%d", &C[i]), q[i] = q[i-1] + C[i];
}
void pre(){
for(int i=1;i<=n;i++) l[i] = r[i] = -inf;
for(int i=2;i<=n;i++){
for(int j=1;j<i;j++)
l[i] = max(l[i], q[i-1] - q[j-1] - (lc+rc)*(i-j));
l[i] = max(l[i], 0);
}
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++)
r[i] = max(r[i], q[j] - q[i] - (lc+rc)*(j-i));
r[i] = max(r[i], 0);
}
}
void solve(){
int ans = -inf;
//i in j out
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i>j) ans = max(ans, q[i] - q[j-1] + r[i] + l[j] - D[i] - F[j] - lc*(i-j));
else if(i == j) ans = max(ans, C[i] + l[i] + r[i] - D[i] - F[i]);
else ans = max(ans, q[j] - q[i-1] + l[i] + r[j] - D[i] - F[j] - rc*(j-i));
printf("%d", ans);
}
int main(){
data_in();
pre();
solve();
return 0;
}
/*
5 1 1
1 1 1 1 1
1 1 1 1 1
1 1 3 1 1
*/
