cogimyunの小窝

Loading...

Luogu P9688 Colo. 题解

首先,这道题目要求最后保留的序列单调不减,那么同样的颜色必须连续排列

为了保证这一点,我们可以记录下每个颜色第一次出现的位置以及最后一次出现的位置,每次只有当前位置为此颜色的第一个并且上一个位置为此颜色的最后一个才考虑将当前位置接在上一个位置后面。

接下来,我们可以开始考虑如何动态规划,\(dp_{i,j}\) 表示以第 \(i\) 个位置结尾,保留了 \(j\) 个颜色的最大价值。则有 \(dp_{i,j}=max(dp_{i,j},dp_{k,j-1}+h_{i})\) 其中 \(k\) 表示上文中满足上文条件的“上一个位置”, \(h_{i}\) 表示颜色 \(i\) 的价值。

CODE:

#include<bits/stdc++.h>
using namespace std;
int n,f,a[505],h[505],book[505],st[505],en[505];
long long dp[505][505];
int check(int x)//查找第i个颜色的最后出现位置
{
	for(int i=n;i>=1;i--)
		if(a[i]==x)
			return i;
	return -1;
}
int main()
{
	for(int i=0;i<=504;i++)
		fill(dp[i],dp[i]+504,-99999999999999);
	cin>>n>>f;
	dp[0][0]=0;
	st[0]=1;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		if(book[a[i]]==0)
		{
			book[a[i]]=1;
			st[i]=1;
		} //标记该位置是否为此颜色第一次出现
	}
	for(int i=1;i<=n;i++)
	{
		en[i]=check(i);
		cin>>h[i];
	}
	for(int i=1;i<=n;i++)
	 	for(int j=0;j<i;j++)
			for(int k=0;k<=f;k++)
			{
				if(a[i]>a[j]&&st[i]==1&&en[a[j]]==j&&dp[j][k]!=-99999999999999&&dp[j][k]+h[a[i]]>dp[i][k+1])
					dp[i][k+1]=dp[j][k]+h[a[i]];//i号位置接在j号位置后
				else if(a[i]==a[j]&&dp[j][k]!=-99999999999999&&dp[j][k]>dp[i][k])
					dp[i][k]=dp[j][k];//i号位置与j号位置颜色相同,继承j号位置的值
			}
	 long long maxx=-99999999999999;
	 for(int i=1;i<=n;i++)
	 	maxx=max(maxx,dp[i][f]);//寻找保留了f种颜色的价值最大值
	 if(maxx==-99999999999999)//若dp[i][f]从未改变,则此数据无解,输出-1
	 {
	 	cout<<-1;
	 	return 0;
	 }
	 cout<<maxx;
	 return 0;
}

posted @ 2025-10-30 18:31  cogimyun  阅读(1)  评论(0)    收藏  举报