zoukankan      html  css  js  c++  java
  • 解题报告: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
    ",dp[1][n]);
    	return 0;
    }
    
  • 相关阅读:
    trie树
    单调队列
    网络流24题——试题库问题
    费用流的简单应用
    Manacher算法
    KMP算法
    网络流之最小费用最大流
    网络流之二分图匹配【转】
    网络流之最大流
    矩阵快速幂优化菲波那切数列
  • 原文地址:https://www.cnblogs.com/tlx-blog/p/12885487.html
Copyright © 2011-2022 走看看