区间dp 合并 2023 上海 计算机学会 2023 .7 乙组 积木染色(三)

积木染色(三)

内存限制: 256 Mb时间限制: 1000 ms

题目描述

现有由 �n 块小积木拼成的一个长条积木,从左到右的小积木编号依次为 1..�1..n,其中第 �i 块小积木的颜色为 ��ci​。

每次,你可以选择连续一段颜色相同的积木,并将他们统一染成任意你想要的颜色。

请问,最少多少次操作,可以讲所有积木染成相同颜色?

输入格式

输入共两行:
第一行,一个正整数 �n
第二行,�n个正整数 �1,�2,...,��c1​,c2​,...,cn​

输出格式

输出共一个整数,表示答案

数据范围
  • 对于 30%30%的数据,1≤�≤101≤n≤10
  • 对于 60%60%的数据,1≤�≤1001≤n≤100
  • 对于 100%100%的数据,1≤�≤500,1≤��≤�1≤n≤500,1≤ci​≤n
样例数据

输入:5
3 2 2 5 5

输出:

2

// 本题目属于区间dp合并,与石子合并的花费类似 
// 思路 寻找 区间ij 合并的最小花费,默认自己根自己为1次,2个相邻元素不等的次数为2次(1+1),相等的话,还剩1次,最后在整体剪掉1
// 枚举长度len,枚举起始位置i(终止位置j=i+len-1),枚举分割点k(包头不包尾) ,计算dpij 的最小花费,ai==aj  dpij=min dpi+1j ,dpij-1
//不等的话,dpij ,就需要枚举分割点k了,看哪个分割点的效果最好 dpij=min(dpij,dpik+dpk+1j)

// 本题目属于区间dp合并,与石子合并的花费类似 
#include <bits/stdc++.h>
using namespace std;
int dp[505][505];
int a[505];
 
int main()
 {
   int n;
   cin>>n;
   int i,j,k,len;
   for(i=1;i<=n;i++)
   {
   		cin>>a[i];
   }
	memset(dp,0X3f,sizeof(dp));
	for(i=1;i<=n;i++)
	dp[i][i]=1; // 自己到自己1次,最后在整体剪掉1 
	// 长度循环len,起始位置循环i,终止点j,分割点循环k 
    for(len=2;len<=n;len++)
    {	
	  for(i=1;i+len-1<=n;i++)
	  {
	  	j=i+len-1;// 终止元素位置 
			if (a[i] == a[j]) // 首尾相等的话,可以 i+1-j,或者i,j-1 变成而来,不需要增加次数 
			dp[i][j] = min(dp[i+1][j], dp[i][j-1]);
			else
			 {
				for(k=i;k<j;k++)// 分割点 k i k,k+1-j 2部分  次数之和 
				{
					dp[i][j] = min(dp[i][j], dp[i][k]+dp[k+1][j]);
				}
			}
		}
	}
	cout << dp[1][n]-1;	
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值