• [一道区间dp][String painter]


    http://acm.hdu.edu.cn/showproblem.php?pid=2476

    String painter

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


    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

     题意:有两个字符串,A串和B串,每次可以对A串一个区间进行涂改,使该区间所有字母变成任意一种字母,求使A串变成B串需要的最少操作次数

    题解:首先考虑一个简化的问题,把一个空串涂改成B串需要的操作数,显然可以通过最基本的区间dp进行解决,转移方程为if(B[i]==B[k])dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]);else dp[i][j]=min(dp[i][j],min(dp[i][k]+dp[k+1][j],dp[i][k-1]+dp[k][j]));然后考虑A串不是空串,那么如果A[i]==B[i],则有ans[i]=ans[i-1],如果A[i]!=B[i],那么ans[i]=min(ans[j]+dp[j][i])。

    普通的循环迭代版本

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define debug(x) cout<<"["<<#x<<"]"<<" is "<<x<<endl;
     4 char ch[105],ch2[105];
     5 int dp[105][105],ans[105];
     6 const int inf=1e8;
     7 int main(){
     8     while(scanf("%s",ch+1)!=EOF){
     9         scanf("%s",ch2+1);
    10         int len=strlen(ch+1);
    11         for(int i=1;i<=len;i++){
    12             for(int j=1;j<=len;j++){
    13                 if(i>j)dp[i][j]=0;
    14                 else if(i==j)dp[i][j]=1;
    15                 else dp[i][j]=inf;
    16             }
    17         }
    18         for(int i=2;i<=len;i++){
    19             for(int j=1;j+i-1<=len;j++){
    20                 for(int k=j+1;k<=j+i-1;k++){
    21                     if(ch2[j]==ch2[k])dp[j][j+i-1]=min(dp[j][j+i-1],dp[j][k-1]+dp[k+1][j+i-1]);
    22                     else dp[j][j+i-1]=min(dp[j][j+i-1],min(dp[j][k]+dp[k+1][j+i-1],dp[j][k-1]+dp[k][j+i-1]));
    23                 }
    24             }
    25         }
    26         for(int i=1;i<=len+1;i++){
    27             ans[i]=inf;
    28         }
    29         ans[1]=0;
    30         for(int i=1;i<=len;i++){
    31             if(ch[i]==ch2[i]){
    32                 ans[i+1]=min(ans[i+1],ans[i]);
    33             }
    34             else{
    35                 for(int j=1;j<=i;j++){
    36                     ans[i+1]=min(ans[i+1],ans[j]+dp[j][i]);
    37                 }
    38             }
    39         }
    40         printf("%d
    ",ans[len+1]);
    41     }
    42     return 0;
    43 }
    View Code

    记忆化搜索版本(注意由于sol(1,len)只能保证dp[1][len]被更新,而不能保证所有的dp[i][j]被遍历到,所以需要使用n^2次sol(i,j)保证所有dp[i][j]都被更新了而不再是初始值)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define debug(x) cout<<"["<<#x<<"]"<<" is "<<x<<endl;
     4 char ch[105],ch2[105];
     5 int dp[105][105],ans[105];
     6 const int inf=1e8;
     7 int sol(int l,int r){
     8     if(dp[l][r]!=0x3f3f3f3f)return dp[l][r];
     9     if(l>r)return dp[l][r]=0;
    10     if(l==r)return dp[l][r]=1;
    11     for(int k=l+1;k<=r;k++){
    12         if(ch2[k]==ch2[l]){
    13             dp[l][r]=min(dp[l][r],sol(l+1,k)+sol(k+1,r));
    14         }
    15         else{
    16             dp[l][r]=min(dp[l][r],sol(l+1,r)+1);
    17         }
    18     }
    19     return dp[l][r];
    20 }
    21 int main(){
    22     while(scanf("%s",ch+1)!=EOF){
    23         scanf("%s",ch2+1);
    24         int len=strlen(ch+1);
    25         memset(dp,0x3f3f3f3f,sizeof(dp));
    26         for(int i=1;i<=len;i++){
    27             for(int j=i;j<=len;j++){
    28                 sol(i,j);
    29             }
    30         }
    31        // sol(1,len);
    32         for(int i=1;i<=len+1;i++){
    33             ans[i]=0x3f3f3f3f;
    34         }
    35         ans[1]=0;
    36         for(int i=1;i<=len;i++){
    37             if(ch[i]==ch2[i]){
    38                 ans[i+1]=min(ans[i+1],ans[i]);
    39             }
    40             else{
    41                 for(int j=1;j<=i;j++){
    42                     ans[i+1]=min(ans[i+1],ans[j]+dp[j][i]);
    43                 }
    44             }
    45         }
    46         printf("%d
    ",ans[len+1]);
    47     }
    48     return 0;
    49 }
    View Code
  • 相关阅读:
    财务统计
    Drupal 7 模 .info 文件描述
    怎么样MyEclipse配置Tomcat?
    QQ旅程server分析01-网关server
    UVa 988
    人工智能的策略,如果国家优先发展”梦想成真”?
    苹果公司的新的编程语言 Swift 高级语言(十一)--初始化类的析构函数的一个实例
    【剑指offer】两个队列实现堆栈
    证券从业改革
    Qt调用word 例子
  • 原文地址:https://www.cnblogs.com/MekakuCityActor/p/10808584.html
Copyright © 2020-2023  润新知