J题题解

题解

J题

本题方法为区间dp,方法比较巧妙,可能我比较菜,觉得这题比较难想到。

题意:

题目给你一串数组,每个数字代表一种颜色,连续且相等的颜色,可以连成一个色块,一次可以改变一个色块的颜色,问最少改变几次,能让所有颜色相同。

题解:

1.首先第一步要对这一堆颜色,进行处理,会发现,可以将数组中连续且相同的数写成一个数,如数组[1,2,2,3],我们可以写成[1,2,3],处理后不会影响结果,并且更方便我们讨论。

2.第二步,由于经过处理后的数组,已不存在色块,因此我们可以对其进行变色操作,操作过程中,我们可以选一个点作为变色操作的起点,举个例子比如[1,2,3,4,1]数组,我们从3开始操作,3左边和右边的两个数分别为2和4,必须进行两次操作,将数组变为[1,3,3,3,1],这时这种情况,中间区间全为3,且区间左右两个数,构成了相同的数对,因此只需要一次操作即可,但如若数组为[1,2,3,4,5],则显然在没有相同数对的情况下(设数组长度为n),则一定要改变颜色n-1次,每一次数对,则可以减少一次改变颜色的次数,因此问题就转化成了统计数对的个数。

3.第三步,问题现已经转化成了,运用区间dp统计数对个数的问题,建立二维dp数组dp[i][j]表示在区间i到j外的数对个数,获得状态转移方程:dp[i][j]=max(dp[i-1][j],dp[i][j+1]),若出现数对则进行比较dp[i][j]=max(dp[i][j],dp[i-1][j+1]+1),这样我们最后遍历所有的dp[i][i],表示从i点出发出现的数对个数,得到最大值,最后答案为n-1-数对个数最大值获得答案

代码:

#include<iostream>
#include<cstdio>
#include<stdio.h>
#include<cmath>
#include<algorithm>
#define maxn 5005
using namespace std;
int n;
int a[maxn];
int dp[maxn][maxn];
int jj;
int check(int i,int j){
    return i-1>=0&&j+1<=n&&a[i-1]==a[j+1];
}
int main(void){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
	n=unique(a+1,a+1+n)-a-1;//合并相同颜色
	dp[1][n]=0;//初始数对为0
	for(int k=n-1;k>=1;k--){
		for(int i=1;i+k-1<=n;i++){
			jj=i+k-1;
			dp[i][jj]=max(dp[i-1][jj],dp[i][jj+1]);
			if(check(i,jj))
                dp[i][jj]=max(dp[i][jj],dp[i-1][jj+1]+1);
		}
	}//运用区间dp处理,计算相同数对
	int ans=0;
	for(int i=1;i<=n;i++)
            ans=max(ans,dp[i][i]);
	printf("%d\n",n-1-ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值