蓝桥杯 奇怪的段 dp

84 阅读1分钟

image.png

题目理解

题目的意思是把长度为n的序列划分为多段,每一段都有一个权值。

其中权值表示为:

image.png

即{a1,a2,a3,an}的区间和。

然后呢还让我们每一个权值再乘p,p是一个长度为k的序列:

image.png

最后就是求 每一段的权值乘p 中值最大的那个,表示为:

image.png

思想

我们划分很多段:

image.png dp[i][j]表示i在j段 加权值最大。

image.png

1.  如果不选取a[i]作为一个新的区间的起点,那么dp[i][j]就等于前i-1个数中选取j个区间时的最大加权和值,即dp[i][j]=dp[i-1][j]。
1.  如果选取a[i]作为一个新的区间的起点,那么dp[i][j]就等于前i-1个数中选取j-1个区间时的最大加权和值,即dp[i][j]=dp[i-1][j-1],再加上a[i]*b[j]的值。

code

#include<bits/stdc++.h> 
using namespace std;
#define int long long
#define ll long long
const int N=2e6+10;
const int mo=1e9+7;
int n,m,sum,x,y,z,k,len,a[N],b[N],c[N],f[N],p[N],dp[100001][201];
void solve()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];  //{a1,a2,a3,an}
	}
	for(int i=1;i<=m;i++)
	{
		cin>>b[i];  //{p1,p2,p3,pn}
	}
	for(int i=1;i<=m;i++)
	{
		dp[0][i]=-1e18;   //除了dp[0][0]初始化为0,剩下的全部初始化为不可达
	}
	for(int i=1;i<=n;i++)
	{
		dp[i][0]=-1e18;
		for(int j=1;j<=m;j++)
		{
			dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+a[i]*b[j];
		}
	}
	cout<<dp[n][m];
} 
signed main()
{
	ios_base::sync_with_stdio(false), cin.tie(nullptr);
    int t=1;

    while(t--)
    {
    	solve();
	}
}