[校内oj1881]项链染色 区间DP

在这里插入图片描述

一句话题意:

环上区间染色,区间有长度限制,求染成所需颜色的最小次数。

分析:

  • 先把环拆开。
  • 这题首先应该有一个基础的模型:给定一个长度为n的串,每个珠子都有颜色。你可以染一个任意长度的区间,求最小次数。
  • 考虑染色的时候其实只有两种情况,一个是先染了一个大区间,然后中间染了一些小的。一个是很多歌小区间拼成一个大区间。设 f [ i ] [ j ] f[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]) 。当 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])
  • 再回到问题上,我们一次最多染长度为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;
}

猜你喜欢

转载自blog.csdn.net/qq_39759315/article/details/88933461