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;
}

浙公網安備 33010602011771號