【bzoj1260】涂色paint[CQOI2007](区间dp)

  题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1260

  这道题其实和codeforces607B有点像,然而做过原题的我居然没看出来。。思想僵化。。

  首先,题目中每次染色的是一段连续区间,大概就能想到区间dp,于是我们可以设$ f[l][r] $表示区间$ [l,r] $需要染的次数。

  转移的话,首先我们可以把区间$ [l,r] $拆成两部分分别染,此时$ f[l][r]=\min \left\{f[l][k]+f[k+1][r] \right\} \ (l<=k<r) $,答案就是$ f[1,n] $。

  此外如果第$ l $和$ r $个位置颜色相同,还可以同时染色,这样有三种情况:

  1、把区间$ [l,r] $染色,然后继续染区间$ f[l+1,r-1] $,此时$ f[l][r]=f[l+1][r-1]+1 $;

  2、对于区间$ [l+1,r] $的染色方案中把位置$ r $染上色的区间,将其左端点拉到位置$ l $,使位置$ l $染上色,此时$ f[l][r]=f[l+1][r] $;

  3、对于区间$ [l,r-1] $的染色方案中把位置$ l $染上色的区间,将其右端点拉到位置$ r $,使位置$ r $染上色,此时$ f[l][r]=f[l][r-1] $;

  于是这样转移方程就胡出来了。。

  代码:

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define ull unsigned long long
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define lowbit(x) (x& -x)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define eps 1e-18
#define maxn 100020
inline ll read(){ll tmp=0; char c=getchar(),f=1; for(;c<'0'||'9'<c;c=getchar())if(c=='-')f=-1; for(;'0'<=c&&c<='9';c=getchar())tmp=(tmp<<3)+(tmp<<1)+c-'0'; return tmp*f;}
inline ll power(ll a,ll b){ll ans=0; for(;b;b>>=1){if(b&1)ans=ans*a%mod; a=a*a%mod;} return ans;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void swap(int &a,int &b){int tmp=a; a=b; b=tmp;}
using namespace std;
int f[60][60];
char s[60];
int n;
int main()
{
    scanf("%s",s); n=strlen(s);
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=n;i++)f[i][i]=1;
    for(int i=2;i<=n;i++)
        for(int l=1;l<=n-i+1;l++){
            int r=l+i-1;
            if(s[l-1]==s[r-1])f[l][r]=min(f[l+1][r-1]+1,min(f[l+1][r],f[l][r-1]));
            for(int k=l;k<r;k++)
                f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);
        }
    printf("%d\n",f[1][n]);
}
bzoj1260

 

posted @ 2018-07-28 21:16  QuartZ_Z  阅读(194)  评论(0编辑  收藏  举报