声明
此题解借鉴了luogu大佬BoAn的题解此处仅为记录自己的做题过程
题目大意
给出一个有n个数的序列 a [ 1 ] , a [ 2 ] … … a [ n ] a[1],a[2]……a[n] a[1],a[2]……a[n],使得在 i < = j < = k i<=j<=k i<=j<=k的条件下,令 p ∗ a [ i ] + q ∗ a [ j ] + r ∗ a [ k ] p*a[i]+q*a[j]+r*a[k] p∗a[i]+q∗a[j]+r∗a[k]的值最大并输出这个值
输入格式
第一行四个数 n 、 p 、 q 、 r n、p、q、r n、p、q、r,第二行 n n n个数,第 i i i个数为 a [ i ] a[i] a[i]的值
输出格式
一行,为 p ∗ a [ i ] + q ∗ a [ j ] + r ∗ a [ k ] p*a[i]+q*a[j]+r*a[k] p∗a[i]+q∗a[j]+r∗a[k]的最大值 ( i < = j < = k ) (i<=j<=k) (i<=j<=k)
思路
CF上也有标签显示这道题目可以用DP做
那我们考虑DP的做法
首先状态表示为
f
i
,
1
表示前
i
个数中
p
∗
a
i
的最大值
f
i
,
2
表示前
i
个数中
p
∗
a
i
+
q
∗
a
j
的最大值
f
i
,
3
表示前
i
个数中
p
∗
a
i
+
q
∗
a
j
+
r
∗
a
k
的最大值
p
,
q
,
r
,
a
i
,
a
j
,
a
k
与题目表示的意思相同
f_{i,1}表示前i个数中p*a_i的最大值 \\ f_{i,2}表示前i个数中p*a_i + q * a_j的最大值 \\ f_{i,3}表示前i个数中p*a_i + q * a_j + r * a_k的最大值 \\ p,q,r,a_i,a_j,a_k与题目表示的意思相同
fi,1表示前i个数中p∗ai的最大值fi,2表示前i个数中p∗ai+q∗aj的最大值fi,3表示前i个数中p∗ai+q∗aj+r∗ak的最大值p,q,r,ai,aj,ak与题目表示的意思相同
那么状态转移方程为
f
i
,
1
=
m
a
x
(
f
i
−
1
,
1
,
p
∗
a
i
)
f
i
,
2
=
m
a
x
(
f
i
−
1
,
2
,
f
i
,
1
+
q
∗
a
i
)
f
i
,
3
=
m
a
x
(
f
i
−
1
,
3
,
f
i
,
2
+
r
∗
a
i
)
f_{i,1} = max(f_{i - 1,1},p * a_i) \\ f_{i,2} = max(f_{i - 1,2},f_{i,1} + q * a_i) \\ f_{i,3} = max(f_{i - 1,3},f_{i,2} + r * a_i)
fi,1=max(fi−1,1,p∗ai)fi,2=max(fi−1,2,fi,1+q∗ai)fi,3=max(fi−1,3,fi,2+r∗ai)
每次只需要便利一次数组时间复杂度为
O
(
n
)
O(n)
O(n)
同时提醒一下
1、考虑到有负数,如果不特判,最大值为
0
0
0
2、我习惯性开long long的所以不知道会不会爆int,但是大佬的题解里提醒说不开long long可能会见祖宗
Code:
#include <iostream>
using namespace std;
#define int long long
const int N = 100010;
int f[N][4];
int n, p, q, r;
int a[N];
signed main()
{
cin >> n >> p >> q >> r;
for (int i = 1; i <= n; i++) cin >> a[i];
f[1][1] = p * a[1];
for (int i = 2; i <= n; i++) f[i][1] = max(f[i - 1][1], p * a[i]);
f[1][2] = f[1][1] + q * a[1];
for (int i = 2; i <= n; i++) f[i][2] = max(f[i - 1][2], f[i][1] + q * a[i]);
f[1][3] = f[1][2] + r * a[1];
for (int i = 2; i <= n; i++) f[i][3] = max(f[i - 1][3], f[i][2] + r * a[i]);
cout << f[n][3];
return 0;
}