zoukankan      html  css  js  c++  java
  • BZOJ1260: [CQOI2007]涂色paint

    1260: [CQOI2007]涂色paint

    Time Limit: 30 Sec  Memory Limit: 64 MB

    Description

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

    Input

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

    Output

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

    Sample Input

     

    Sample Output

    【样例输入1】
    AAAAA

    【样例输入1】
    RGBGR

    【样例输出1】
    1

    【样例输出1】
    3


    HINT

    40%的数据满足:1<=n<=10
    100%的数据满足:1<=n<=50

    from:

    a799091501

    经典的区间dp题

    对于一个给定的结束状态,我们考虑他是怎么转移的:

    显然 只能是由一个子区间再往左涂一次或者再往右涂一次

    那么对于任意一个大于二的序列都可以分成两个子序列,所以这就是一道区间dp了!(鼓掌!

    很容易发现 如果最s[l]==s[l+1]||s[r]==s[r-1] 那么就不需要多余的次数来涂他了(因为一次可以把这两个都涂上)

    但是下一个可能就没有那么好理解了(我居然浪费了两个多小时,我真是太弱啦!

    如果s[l]==s[r]

    那么可以证明 涂了l(或者r)的时候,这一次涂色一定同时涂上了r 不然不可能是最优解(因为即使r不是另一个区间所需要的颜色,答案也不会变的更差)

    也就是说,转移方程为dp[l][r]=min(dp[l+1][r-1]+1,min(dp[l+1][r],dp[l][r-1]))  (s[l]==s[r])

    因为取l和r,对另一个元素的贡献是等效的 所以只需要在他们中取min,并且这一次操作不会对答案产生改变

    当然 另一种取法就是直接一笔从[l+1]画到[r-1] 这样答案++

    以上属于特殊情况 对于其他的情况 只需要区间dp的经典递推式就可以了

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<cstdlib>
     7 #include<vector>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef long double ld;
    11 typedef pair<int,int> pr;
    12 const double pi=acos(-1);
    13 #define rep(i,a,n) for(int i=a;i<=n;i++)
    14 #define per(i,n,a) for(int i=n;i>=a;i--)
    15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
    16 #define clr(a) memset(a,0,sizeof(a))
    17 #define pb push_back
    18 #define mp make_pair
    19 #define fi first
    20 #define sc second
    21 #define pq priority_queue
    22 #define pqb priority_queue <int, vector<int>, less<int> >
    23 #define pqs priority_queue <int, vector<int>, greater<int> >
    24 #define vec vector
    25 ld eps=1e-9;
    26 ll pp=1000000007;
    27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
    28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
    29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
    30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
    31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
    32 ll read(){ ll ans=0; char last=' ',ch=getchar();
    33 while(ch<'0' || ch>'9')last=ch,ch=getchar();
    34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    35 if(last=='-')ans=-ans; return ans;
    36 }
    37 const int N=100;
    38 int f[N][N];
    39 char ch[N];
    40 int main(){
    41     scanf("%s",ch+1); int n=strlen(ch+1);
    42     for (int p=1;p<=n;p++){
    43         for (int i=1;i<=n;i++){
    44             int j=i+p-1;
    45             if (j>n) continue;
    46             f[i][j]=j-i+1;
    47             if (i!=j && ch[i]==ch[j]) f[i][j]=min(f[i][j],f[i+1][j]),f[i][j]=min(f[i][j],f[i+1][j]);
    48             for (int k=i;k<j;k++){
    49                 f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
    50             }
    51         }
    52     }
    53     printf("%d",f[1][n]);
    54     return 0;
    55 }
    View Code

     

  • 相关阅读:
    Building a flexiable renderer
    Indirect Illumination in mental ray
    我的心情
    Cellular Automata
    Subsurface Scattering in mental ray
    Shader Types in mental ray
    BSP Traversal
    我的渲染器终于达到了MR的速度
    How to handle displacement and motion blur
    说明
  • 原文地址:https://www.cnblogs.com/SXia/p/7614779.html
Copyright © 2011-2022 走看看