传送门

https://www.cnblogs.com/violet-acmer/p/9852294.html

题意:

  给定字符串A,B,每次操作可以将字符串A中区间[ i , j ]的字符变为ch,问最少需要多少次操作可以使 A == B。

题解:

  这道题,卡了我好久好久,这期间也尝试用了一些骚操作,然而并没有什么卵用,无奈之举,百度找了巨巨的博客看。

  看了三四篇博客,在经过自己的纠结,终于弄懂了。

  首先,这道题需要经过两次DP:

  ① : 第一次是求出将空字符串 S 变为 B 所需的最少操作,定义dp[ i ][ j ] : S[ i,......,j ] == B[ i,......,j ] 所需的最少操作。

  ② : dp[ ][ ] 求出后,然后根据巨巨的解释就是“A串中的字符与B字符串对应的位置可能存在相同的情况,所以又存在减少次数的可能,这里又会再次用DP计算”

  最难理解的便是dp[ ][ ]求解的过程。

  状态转移方程如下:

 );
 mem(dp,);
 ;i <= lenA;++i)
     dp[i][i]=;//S[i]变为B[i]需要一次操作,不要忘了S[]为空字符串
 ;len <= lenA;++len)//区间长度
 {
     ;i+len- <= lenA;++i)//求解dp[i,j]
     {
         ;
         //初始化dp[i][j]
         //dp[i][j]=( S[i+1,j]变为B[i+1,j]所需的最少操作dp[i+1][j] )+( S[i]变为B[i]需要一次操作 )
         dp[i][j]=dp[i+][j]+;
         ;k <= j;++k)
             if(B[i] == B[k])
                 dp[i][j]=min(dp[i][j],dp[i+][k-]+dp[k][j]);
     }
 }

  我的理解:

    ①如果B[ i+1,......,j ]中的字符都不等于 B[ i ],那么 dp[ i ][ j ]=dp[ i+1 ][ j ]+1 ;  这也就对应了初始化dp[ i ][ j ]语句,却不会执行for( )循环中的 if 语句。

    ②如果B[ i+1,......,j ]含有字符等于 B[ i ],如图所示

      

      当 k = k1 时,状态转移方程  dp[ i ][ j ]=min( dp[ i ][ j ] , dp[ i+1 ][ k-1 ]+dp[ k ][ j ] ); 还是比较好理解的,就是在将 S[ k1 ] 变为 B[ i ]的时候一次性也将

    S[ ①,......,② ] 变成 B[ i ],因为 B[ k1 ] 是第一个等于 B[ i ] 的,所以 [ ①,......,② ]区间并没有等于 B[ i ] 的字符,那么,将 S[ ①,......,② ] 变为"B[ i ]"或"为空"

    对之前所求的 dp[ ①,......,② ] 无影响。

      当 k = k2 时,为什么还是用 dp[ i+1 ][ k-1 ] 呢?

      思路依旧是 k = k1 时的思路,“在将 S[ k2 ] 变为 B[ i ]的时候一次性也将 S[ ①,......,④ ] 变成 B[ i ]”,那么,该如何求解 dp[ ①,......,④ ]呢?

      根据状态转移方程 dp[ i ][ j ] = min( dp[ i ][ j ] , dp[ i ][ k-1]+dp[ k ][ j ] ),所以说 整体的dp ≤ 部分的dp,即dp[ i ][ j ] ≤ dp[ i ][ k-1 ]+dp[ k ][ j ]。

      当 k = k3,k4,..... 时同理。

AC代码:

 #include<iostream>
 #include<cstdio>
 #include<cstring>
 using namespace std;
 #define mem(a,b) memset(a,b,sizeof(a))
 +;

 char A[maxn],B[maxn];
 int dp[maxn][maxn];
 int f[maxn];

 int Solve()
 {
     );
     mem(dp,);
     ;i <= lenA;++i)
         dp[i][i]=;//S[i]变为B[i]需要一次操作,不要忘了S[]为空字符串
     ;len <= lenA;++len)//区间长度
     {
         ;i+len- <= lenA;++i)//求解dp[i,j]
         {
             ;
             dp[i][j]=dp[i+][j]+;
             ;k <= j;++k)
                 if(B[i] == B[k])
                     dp[i][j]=min(dp[i][j],dp[i+][k-]+dp[k][j]);
         }
     }
     ;i <= lenA;++i)
     {
         f[i]=dp[][i];
         if(A[i] == B[i])
             f[i]=f[i-];
         else
         {
             //如果A[i] != B[i]
             //那么,从[1,i]之间任意位置断开成[1,k]和[k+1,j],求两部分区间的最小值
             ;k <= i;++k)
                 f[i]=min(f[i],f[k]+dp[k+][i]);
         }
     }
     return f[lenA];
 }
 int main()
 {
     ,B+))
     {
         printf("%d\n",Solve());
     }
     ;
 }

    其实,感觉对 k > k1 时的理解还是有点牵强,先放放吧,过一段时间在回头理解一下,说不定就顿悟了呢。

    还望有理解的巨巨留言相告,定感激不尽

hdu 2476"String painter"(区间DP)的更多相关文章

  1. HDU 2476 String painter(区间dp)

    题意: 给定两个字符串,让求最少的变化次数从第一个串变到第二个串 思路: 区间dp, 直接考虑两个串的话太困难,就只考虑第二个串,求从空白串变到第二个串的最小次数,dp[i][j] 表示i->j ...

  2. HDU 2476 String painter(区间DP+思维)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2476 题目大意:给你字符串A.B,每次操作可以将一段区间刷成任意字符,问最少需要几次操作可以使得字符串 ...

  3. HDU 2476 String painter(区间DP)

    String painter Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...

  4. hdu 2476 (string painter) ( 字符串刷子 区间DP)

    String painter Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  5. HDU 2476 String painter (区间DP)

    题意:给出两个串a和b,一次只能将一个区间刷一次,问最少几次能让a=b 思路:首先考虑最坏的情况,就是先将一个空白字符串刷成b需要的次数,直接区间DP[i][j]表示i到j的最小次数. 再考虑把a变成 ...

  6. HDU 2476 String painter(记忆化搜索, DP)

    题目大意: 给你两个串,有一个操作! 操作时可以把某个区间(L,R) 之间的所有字符变成同一个字符.现在给你两个串A,B要求最少的步骤把A串变成B串. 题目分析: 区间DP, 假如我们直接想把A变成B ...

  7. hdu2476 String painter(区间dp)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=2476 Problem Description There are two strings ...

  8. HDU2476 String painter —— 区间DP

    题目链接:https://vjudge.net/problem/HDU-2476 String painter Time Limit: 5000/2000 MS (Java/Others)    Me ...

  9. uva live 4394 String painter 区间dp

    // uva live 4394 String painter // // 这一题是训练指南上dp专题的习题,初看之下认为仅仅是稍微复杂了一点 // 就敲阿敲阿敲,两个半小时后,发现例子过了.然而自己 ...

随机推荐

  1. 多IP地址--笔记

    多IP 地址特性使虚拟用户可以在一个load generator上运行且被识别为多个IP地址 1 虚拟IP是同一个generator上的多个IP,这种分配过程由controller自动来进行 2 对于 ...

  2. 获取DataSet中某行某列的数据

    LabelText = DataSet11.Tables("COMM.USERS").Rows[0]["User_Name"].tostring() Label ...

  3. C#里XML(JSON)序列化时,自动隐藏值为Null的成员的输出

    从StackOverflow里找到的答案.发现对最新的Newtownsoft的JSON序列化也同样适用. https://stackoverflow.com/questions/5818513/xml ...

  4. [开源 .NET 跨平台 Crawler 数据采集 爬虫框架: DotnetSpider] [一] 初衷与架构设计

    [DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 五.如何做全站采集 为什么要造轮子 同学们可以去各大招聘网站查看一下爬虫工程师 ...

  5. JdbcTemplate的运用 (也是数据源的一种)

  6. JavaScript的 sourcemap 的理解

    当我们在使用vue-cli 开发项目完成后, 就要进行部署,执行npm run build 命令,你会发现它生成.js文件的同时,还会生成一个对应的.map 文件. 当时查了一下, .map 文件的主 ...

  7. Sql Server设置主键和外键

    设置主键 https://jingyan.baidu.com/article/9158e0003349a7a2541228fd.html 设置外键 https://jingyan.baidu.com/ ...

  8. [BZOJ 2083] [POI 2010] Intelligence test

    Description 霸中智力测试机构的一项工作就是按照一定的规则删除一个序列的数字,得到一个确定的数列.Lyx很渴望成为霸中智力测试机构的主管,但是他在这个工作上做的并不好,俗话说熟能生巧,他打算 ...

  9. Vuex以及axios

    Vuex 简介 vuex是一个专门为Vue.js设计的集中式状态管理架构. 状态? 我们把它理解为在data中需要共享给其他组件使用的部分. Vuex和单纯的全局对象有以下不同: 1.Vuex 的状态 ...

  10. 醉汉随机行走/随机漫步问题(Random Walk Randomized Algorithm Python)

    世界上有些问题看似是随机的(stochastic),没有规律可循,但很可能是人类还未发现和掌握这类事件的规律,所以说它们是随机发生的. 随机漫步(Random  Walk)是一种解决随机问题的方法,它 ...