CF885B Marvolo Gaunt‘s Ring

声明

此题解借鉴了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] pa[i]+qa[j]+ra[k]的值最大并输出这个值

输入格式

第一行四个数 n 、 p 、 q 、 r n、p、q、r npqr,第二行 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] pa[i]+qa[j]+ra[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个数中pai的最大值fi,2表示前i个数中pai+qaj的最大值fi,3表示前i个数中pai+qaj+rak的最大值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(fi1,1,pai)fi,2=max(fi1,2,fi,1+qai)fi,3=max(fi1,3,fi,2+rai)
每次只需要便利一次数组时间复杂度为 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值