记录大佬的思路

洛谷染色问题,即2024CSP-S第三题。
原题复述:
给定一个长度为 n 的正整数数组 A,其中所有数从左至右排成一排。你需要将 A 中的每个数染成红色或蓝色之一,然后按如下方式计算最终得分:
设 C 为长度为 n 的整数数组,对于 A 中的每个数 左侧没有与其同色的数,则令 Ci=0。否则,记其左侧与其最靠近的同色数为 Aj ,若 Ai=Aj,则令 Ci=Ai
否则Ci为0。最终得分为 C 中所有整数的和,即你需要最大化最终得分,请求出最终得分的最大值。

一开始考虑肯定是简单的搜索,很可惜,没有重复子问题,所以记忆化搜索用不上。暴搜显然会寄,测试通过前四个点。
#include<bits/stdc++.h>
using namespace std;
#define max(a,b) (a>b?a:b)
int t,n;int a[200001];int ans[20001];int ind=0;
map<int,int>m;
int s(int ind,int stat)
{
    
    if(ind==n)
    {
        //cout<<bitset<6>(stat)<<endl;
        /*if(m.find(stat)!=m.end())
            return m[stat];*/
        int ans=0;
        for(int i=1;i<n;i++)
        {
            int s=(stat&(1<<i))>>i;//
            int c=0;
            for(int j=i-1;j>=0;j--)
            if((s==((stat&(1<<j))>>j)))
            {
                c=a[i]==a[j]?a[i]:0;
                break;
            }
            //cout<<c<<endl;
            ans+=c;
        }
        //cout<<bitset<9>(stat)<<" "<<ans<<endl;
        //m[stat]=ans;
        return ans;
    }
    int a=s(ind+1,(stat|(1<<ind)));
    int b=s(ind+1,stat);
    int ans=max(a,b);
    return ans;
}

int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        memset(a,0,sizeof(a));
        for(int i=0;i<n;i++)
            cin>>a[i];
        ans[ind++]=s(0,0);
    }
    for(int i=0;i<ind;i++)
        cout<<ans[i]<<endl;
    return 0;
}
搜索用不上,下面就要考虑规划,以下是题解大佬的动态规划代码。每次f[i]只会在a[i]已经出现过时产生更新。以s记录相邻的a[i]元素产生的增益。选择lst[a[i]]+1的原因是lst[a[i]]+1可能与lst[a[i]]之前的某点产生增益(之后的增益均被s记录)。
#include <bits/stdc++.h>

#define int long long
#define rint register int
#define endl '\n'
#define m(a) memset(a, 0, sizeof a)

using namespace std;

const int N = 1e6 + 5;

int n, T;
int a[N], lst[N], f[N];
int s[N], ans; 

signed main() 
{
	cin >> T;
	while (T--) 
	{
		cin >> n;
		m(a), m(lst), m(f), m(s);
		for (rint i = 1; i <= n; i++) cin >> a[i];
		for (rint i = 2; i <= n; i++) s[i] = (a[i] == a[i - 1] ? s[i - 1] + a[i] : s[i - 1]);
		for (rint i = 1; i <= n; i++) 
		{
			f[i] = f[i - 1];
			if (lst[a[i]]) f[i] = max(f[i], f[lst[a[i]]+1] + a[i] + s[i] - s[lst[a[i]]+1]);
			lst[a[i]] = i;
		}
		cout << f[n] << endl;
	} 
	return 0;
}
posted @ 2024-11-07 21:18  邓佑孤  阅读(5)  评论(0编辑  收藏  举报