一句话题意:
环上区间染色,区间有长度限制,求染成所需颜色的最小次数。
分析:
- 先把环拆开。
- 这题首先应该有一个基础的模型:给定一个长度为n的串,每个珠子都有颜色。你可以染一个任意长度的区间,求最小次数。
- 考虑染色的时候其实只有两种情况,一个是先染了一个大区间,然后中间染了一些小的。一个是很多歌小区间拼成一个大区间。设 f [ i ] [ j ] f[i][j] f[i][j]表示 ( i , j ) (i,j) (i,j)这个区间被染色的最小次数。 f [ i ] [ j ] = m i n ( f [ i ] [ j ] , f [ i ] [ k ] + f [ k + 1 ] [ j ] ) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j])。当 a [ i ] = a [ j ] a[i]=a[j] a[i]=a[j]时, f [ i ] [ j ] = m i n ( f [ i ] [ j ] , f [ i ] [ j − 1 ] ) f[i][j]=min(f[i][j],f[i][j-1]) f[i][j]=min(f[i][j],f[i][j−1])。
- 再回到问题上,我们一次最多染长度为k的区间,枚举一下起点就好了。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
#define INF 2147483646
#define ll long long
#define R register
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
int x=0,f=1;char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
inline void put(int x)
{
x<0?putchar('-'),x=-x:0;
int num=0;char ch[50];
while(x)ch[++num]=x%10+'0',x/=10;
num==0?putchar('0'):0;
while(num)putchar(ch[num--]);
putchar('\n');return;
}
const int MAXN=202;
int n,m,k,minn=INF;
int a[MAXN<<1],f[MAXN<<1];
int cost[MAXN<<1][MAXN<<1];
inline int min(int x,int y){return x>y?y:x;}
//f[i] 表示前i 个珠子全部染色完毕所需的最小次数
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();k=read();
memset(cost,10,sizeof(cost));
for(int i=1;i<=n;++i)a[i]=read(),a[i+n]=a[i];
for(int i=1;i<=(n<<1);++i)cost[i][i]=1;
for(int len=2;len<=n;++len)
{
for(int i=1;i<=(n<<1)-len+1;++i)
{
int j=i+len-1;
if(a[i]==a[j])cost[i][j]=min(cost[i][j],cost[i][j-1]);
for(int w=i;w<j;++w)cost[i][j]=min(cost[i][j],cost[i][w]+cost[w+1][j]);
}
}
for(int p=1;p<n;++p)
{
memset(f,10,sizeof(f));f[p-1]=0;
for(int i=p;i<=n+p-1;++i)
{
for(int j=max(p-1,i-k);j<i;++j)
{
f[i]=min(f[i],f[j]+cost[j+1][i]);
}
}
minn=min(minn,f[n+p-1]);
}
put(minn);
return 0;
}