……

解题报告:luogu P4170

题目链接:P4170 [CQOI2007]涂色

区间 \(dp\) 好题。

我们假如已经有这个区间的最小步数:

\[BRG \]

如果在区间右端添加一个 R 会怎么样呢?

考虑上一个涂到这个 R 未知的颜色是啥,显然是前面的这些之一或是他自己。

如果是他自己,那么:

\[dp_{l,r}=dp_{l,r-1}+1 \]

如果上一个与他不相同的话,那么设位置为 \(k\)

\[dp_{l,r}=dp_{l,k}+dp_{k+1,r-1}+1 \]

如果上一个颜色与他相同:

\[dp_{l,r}=dp_{l,k}+dp_{k+1,r-1} \]

如果是在右面加元素同理。

\(Code:\)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;

#define inf 1000000000

char s[55];
int n,dp[55][55];

int main()
{
	scanf("%s",s);
	n=strlen(s);
	for(int i=n+1;i>=1;i--) s[i]=s[i-1];
	for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) dp[i][j]=inf;
	for(int i=0;i<=n;i++) dp[i][i]=1;
	for(int i=1;i<=n;i++) for(int j=0;j<i;j++) dp[i][j]=0;
	for(int i=2;i<=n;i++)
	{
		for(int l=1;l+i-1<=n;l++)
		{
			int r=l+i-1;
			dp[l][r]=dp[l][r-1]+1;
			for(int k=r-1;k>=l;k--)
			{
				if(s[k]==s[r]) dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r-1]);
				else dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r-1]+1);
			}
			dp[l][r]=min(dp[l][r],dp[l+1][r]+1);
			for(int k=l+1;k<=r;k++)
			{
				if(s[k]==s[l]) dp[l][r]=min(dp[l][r],dp[k][r]+dp[l+1][k-1]);
				else dp[l][r]=min(dp[l][r],dp[l+1][k-1]+dp[k][r]+1);
			}
		}
	}
	printf("%d\n",dp[1][n]);
	return 0;
}
posted @ 2020-05-13 22:52  童话镇里的星河  阅读(113)  评论(0编辑  收藏  举报