涂色paint_区间DP

Time Limit: 30 Sec  Memory Limit: 64 MB
Submit: 893  Solved: 540
[Submit][Status][Discuss]

Description

假设你有一条长度为5的木版,初始时没有涂过任何颜色。你希望把它的5个单位长度分别涂上红、绿、蓝、绿、红色,用一个长度为5的字符串表示这个目标:RGBGR。 每次你可以把一段连续的木版涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色。例如第一次把木版涂成RRRRR,第二次涂成RGGGR,第三次涂成RGBGR,达到目标。 用尽量少的涂色次数达到目标。

Input

输入仅一行,包含一个长度为n的字符串,即涂色目标。字符串中的每个字符都是一个大写字母,不同的字母代表不同颜色,相同的字母代表相同颜色。

Output

仅一行,包含一个数,即最少的涂色次数。

Sample Input

 

Sample Output

【样例输入1】
AAAAA

【样例输入1】
RGBGR

【样例输出1】
1

【样例输出1】
3

 要使某段涂色次数最少,只要考虑两端的颜色是否相同

若相同,取dp[i+1][j],dp[i][j-1],dp[i+1][j-1]+1中的最小值;

否则寻找k,找到使得dp[i][j]最小的k;

#include<iostream>
#include<string>
#include<string.h>
using namespace std;
const int inf=0x7777777;
int dp[500][500];
int main()
{
    int n,m,i,j,k,len;
    string s;
    while(cin>>s)
    {

        len=s.length();
        s=" "+s;
        for(i=0; i<=len; i++)
        {
            for(j=0; j<=len; j++)
            {
                dp[i][j]=inf;
            }
            dp[i][i]=1;
        }


        for(int h=1;h<=len;h++)
            for(int i=1;i<=len;i++)
            {
                j=i+h;
                if(s[i]==s[j]) dp[i][j]=min(min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1]+1);
                else
                {
                    for(k=i; k<j; k++)
                        dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
                }
            }
        cout<<dp[1][len]<<endl;
    }

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/iwantstrong/p/5750942.html