• HDU 2476:String painter 区间DP好题


    String painter

    题目链接:

    http://poj.org/problem?id=2476

    题意:

    给出两个相同长度的字符串(仅由小写字母组成)s1,s2,每次操作可以将s1的任意一段区间改变成一个相同的字母,求将s1改变成s2所需的最少操作次数。

    题解:

    设dp[i][j]是将s1的区间[i,j]部分改成s2相同部分的最少操作次数,终点状态为dp[1][t]( t 为长度)。

    先求出一个和s2没有任何相同部分的字符串转化为s2所需的最少次数,再求s1转化为s2的最少次数即可。

                  

    代码

    #include<stdio.h>
    #include<string.h>
    const int N=101;
    int dp[N][N];
    char s1[N],s2[N];
    int mmin(int x,int y)
    {
      return x<y?x:y;
    }
    void solve()
    {
      int n,m,x;
      memset(dp,0,sizeof(dp));
      while(~scanf("%s%s",s1+1,s2+1))
      {
        s1[0]=s2[0]='?';
        int t=strlen(s1)-1;
        for(int len=0;len<t;++len)
        for(int i=1;i+len<=t;++i)
        {
          int j=len+i;
          dp[i][j]=dp[i][j-1]+1;
          for(int k=i;k<j;++k)
          {
            if(s2[k]==s2[j])dp[i][j]=mmin(dp[i][j],dp[k+1][j-1]+dp[i][k]);//考虑到s2串为aaaaaaa的情况这里必须是+dp[i][k],而不能是+dp[i][k-1]+1,刷[i,k]的时候顺便刷到 j 就好了
            dp[i][j]=mmin(dp[i][j],dp[i][k-1]+dp[k][j]);
          }
        }
        for(int len=0;len<t;++len)
        for(int i=1;i+len<=t;++i)
        {
          int j=len+i;
          if(s1[j]==s2[j]&&s1[i]==s2[i])
          {
            dp[i][j]=mmin(dp[i][j],dp[i+1][j-1]);
          }
          else
          {
            for(int k=i;k<=j;++k)
              if(dp[i][k]+dp[k+1][j]<dp[i][j])
                dp[i][j]=dp[i][k]+dp[k+1][j];
          }
        }
        printf("%d ",dp[1][t]);
      }
    }
    int main()
    {
      solve();
      return 0;
    }

     
  • 相关阅读:
    你必须用角色管理工具安装Microsoft .NET Framework 3.5
    LINQ 小心Access to modified closure 问题
    .net BCL获取所有磁盘的信息
    对象的序列化和反序列化及其实现和使用
    对于CSDN博客文章不能爬取的问题
    IO与文件读写Java的IO流架构
    对象的深复制与浅复制 实现Cloneable接口实现深复制 序列化实现深复制
    博客园文章爬取代码
    【HtmlParser】HtmlParser使用
    爬虫简单示例,用httpClient4.2.1实现(转载)
  • 原文地址:https://www.cnblogs.com/kiuhghcsc/p/5751989.html
Copyright © 2020-2023  润新知