• HDU_2476_String painter_(区间dp)


    String painter

    Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 3935    Accepted Submission(s): 1833


    Problem Description
    There are two strings A and B with equal length. Both strings are made up of lower case letters. Now you have a powerful string painter. With the help of the painter, you can change a segment of characters of a string to any other character you want. That is, after using the painter, the segment is made up of only one kind of character. Now your task is to change A to B using string painter. What’s the minimum number of operations?
     
    Input
    Input contains multiple cases. Each case consists of two lines:
    The first line contains string A.
    The second line contains string B.
    The length of both strings will not be greater than 100.
     
    Output
    A single line contains one integer representing the answer.
     
    Sample Input
    zzzzzfzzzzz
    abcdefedcba
    abababababab
    cdcdcdcdcdcd
     
    Sample Output
    6
    7
     
    2017.3.18复习,感觉这道题的dp设计很巧妙,还是没有吃透。。。

     
    题意:给定两个等长字符串A、B,一次操作可以将A的任意一段连续的字符变为同一任意字符,问最少多少次操作可以将A变为B。
     
    专门挑的区间dp的题,但是然并卵。。。没思路啊。。。看题解。。。
     
    思路:dp[i][j]:将空串变为B[i-->j]所需要的最少次数。先求出所有dp[i][j],即求出将空串变为B[i-->j]所需最少次数。那么根据dp数组求出最终答案就很容易:
    1.ans[k]=dp[1][k]
     
    2.if(A[k]==B[k])   ans[k]=ans[k-1];     (ans[0]==0)
     else  ans[k]=min(ans[k],ans[t]+ans[t+1][k]);  (1=<t<k)
     
    求dp[i][j]:
    枚举起点i、终点j、遍历[i+1,j]区间k

    for(int j=1;j<=len;j++) //end
    {
      for(int i=j;i>0;i--) //begin
      {
        dp[i][j]=dp[i+1][j]+1;
        for(int k=i+1;k<=j;k++)
          if(B[i]==B[k])
            dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]);
       }
    }

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    char A[105],B[105];
    int dp[105][105];
    int ans[105];
    
    int main()
    {
        while(scanf("%s%s",A+1,B+1)!=EOF)
        {
            memset(dp,0,sizeof(dp));
            memset(ans,0,sizeof(ans));
            int len=strlen(B+1);
            for(int j=1;j<=len;j++)  //end
            {
                for(int i=j;i>0;i--)  //begin
                {
                    dp[i][j]=dp[i+1][j]+1;
                    for(int k=i+1;k<=j;k++)  //一定是从左往右找重的
                        if(B[i]==B[k])
                            dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]);
                }
            }
            for(int i=1;i<=len;i++)
            {
                ans[i]=dp[1][i];
                if(A[i]==B[i])
                    ans[i]=ans[i-1];
                else
                {
                    for(int j=1;j<i;j++)
                        ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
                }
            }
            printf("%d
    ",ans[len]);
        }
        return 0;
    }

     

     

  • 相关阅读:
    Win10怎么默认用Windows照片查看程序打开图片
    Class类文件结构——访问标志
    栈的压入弹出序列
    Java中length,length()以及size()的区别
    包含min函数的栈
    extends和implements的区别
    顺时针打印矩阵
    二叉树的镜像
    Class类文件结构解读——常量池
    进制、字(word)、字节(byte)、位(bit)的关系
  • 原文地址:https://www.cnblogs.com/jasonlixuetao/p/6503388.html
Copyright © 2020-2023  润新知