zoukankan      html  css  js  c++  java
  • [一道区间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
  • 相关阅读:
    新概念英语第三册21-40课(转)
    多线程---线程通信
    多线程----线程同步
    多线程----线程创建的四种方式
    从0开始整合SSM框架-1.mybatis
    easyUI datagrid 动态绑定列名称
    java分享第五天(数组)
    java分享第四天(循环)
    java分享第三天(异常)
    java分享第二天(变量及命名规范)
  • 原文地址:https://www.cnblogs.com/MekakuCityActor/p/10808584.html
Copyright © 2011-2022 走看看