题目大意:有两个字符串A,B,一次刷可以把A串一段刷成同一个字母,问至少要刷几次才能把A串变成B串。串长≤100。

  本来以为是个很简单的区间DP,后来发现直接区间DP是不行的,这玩意有后效性:刷完一整块之后这一块就变了。

  对于这种问题不如干脆利落一点,直接把 f[ ][ ]设成将空串(即不需要考虑A与B的相同)刷成B串的最小次数。

  这个时候的转移方程就是:

  for(int i=1;i<=n;++i)f[i][i]=1;for(int len=1;len<n;++len)for(int i=1;i+len<=n;++i){int j=i+len;f[i][j]=f[i+1][j]+1;for(int k=i+1;k<=j;++k)if(B[i]==B[k])f[i][j]=min(f[i][j],f[i+1][k]+f[k+1][j]);}

  这个转移方程是很巧妙的。

  首先赋值最坏情况,作为最大值,然后枚举k,进行更新。

  转移方程的思想是:如果在B串中,i和k是一样的,就可以划分区间进行更新。

  结论:在涂色的时候,区间的一个端点,一定可以作为第一个涂色。

  证明:区间涂色有两种方法:分成左右 / 先整个涂一遍再在里面涂。

  分成左右是子问题,先整个涂的话就可以先选择这个端点涂。

  所以在转移时,如果i和k是一样的,则可以有f[i][k]=f[i+1][k],只需要在涂k的时候把整个区间涂上就可以了。

  同样可以用上面的子问题思考方式证明。

  这样就把"空串变B串"解决了。但是我们是要把A串变B串,答案还需要统计一遍。

  设g[i]表示A串从1到i全部被涂成B的最小步数,用f来更新g。

  这个时候转移方程就是这样:

  g[1]=A[1]==B[1]?0:1;for(int i=2;i<=n;++i){if(A[i]==B[i]){g[i]=g[i-1];continue;}g[i]=f[1][i];for(int j=1;j<i;++j)g[i]=min(g[i],g[j]+f[j+1][i]);}

  这个转移也是比较有意思的,这里就不做分析了。

  对于这种显然只能用DP来做的、一般的转移又有后效性的题,不妨状态设大气一点,直接忽略后效性带来的影响,再变换方式统计答案。

#include    <iostream>
#include    <cstdio>
#include    <cstdlib>
#include    <algorithm>
#include    <vector>
#include    <cstring>
#include    <queue>
#include    <complex>
#include    <stack>
#define LL long long int
#define dob double
#define FILE "4394"
using namespace std;const int N = 110;
int n,f[N][N],g[N];
char A[N],B[N];inline int gi(){int x=0,res=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();}while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();return x*res;
}inline void solve(){n=strlen(A+1);for(int i=1;i<=n;++i)f[i][i]=1;for(int len=1;len<n;++len)for(int i=1;i+len<=n;++i){int j=i+len;f[i][j]=f[i+1][j]+1;for(int k=i+1;k<=j;++k)if(B[i]==B[k])f[i][j]=min(f[i][j],f[i+1][k]+f[k+1][j]);}g[1]=A[1]==B[1]?0:1;for(int i=2;i<=n;++i){if(A[i]==B[i]){g[i]=g[i-1];continue;}g[i]=f[1][i];for(int j=1;j<i;++j)g[i]=min(g[i],g[j]+f[j+1][i]);}printf("%d\n",g[n]);
}int main(){freopen(FILE".in","r",stdin);freopen(FILE".out","w",stdout);while(~scanf("%s%s",A+1,B+1))solve();fclose(stdin);fclose(stdout);return 0;
}

String painter

转载于:https://www.cnblogs.com/fenghaoran/p/7671155.html

UVALive 4394 String painter相关推荐

  1. UVALive 4394 String painter——dp

    设ans[i]为区间[1,i]已经染好的最小花费 若s[i]=t[i],ans[i]=ans[i-1] 否则ans[i]=min{ans[j-1]+cost(j,i)},cost(j,i)为区间[j, ...

  2. uva live 4394 String painter 间隔dp

    // uva live 4394 String painter // // 问题是,在培训指导dp运动主题,乍一看,我以为只是一点点复杂 // A A磕磕磕,两个半小时后,.发现超过例子.然而,鉴于他 ...

  3. LA 4394 String painter 区间DP -

    题目地址:http://vjudge.net/problem/UVALive-4394 很明显的区间DP 区间DP的套路就是 d[i][j]的在区间 (i,j) 刷的次数 转移也一般是 d[i][j] ...

  4. 动态规划训练11 [String painter HDU - 2476]

    String painter HDU - 2476 题意: 我认为这是一道比较难的问题,自己想了很久,没有想出来怎么做,可能是因为思维僵化吧,一直在想怎么直接的由A变到B,事实上,可以有中间桥梁连接A ...

  5. HDU2476:String painter(区间dp)

    原文地址:http://blog.csdn.net/a601025382s/article/details/12379565 原文作者:knownothing String painter Time ...

  6. ACM学习历程—HDU2476 String painter(动态规划)

    http://acm.hdu.edu.cn/showproblem.php?pid=2476 题目大意是给定一个起始串和一个目标串,然后每次可以将某一段区间染成一种字符,问从起始串到目标串最少需要染多 ...

  7. UVAlive 4394

    题目大意:给定两个长度相等,只有小写字母组成的字符串s和t,每步可以把s的一个连续子串刷成同一个字母,问至少需要几步才能把s变成t? 大致方法:先用dp求出从空串刷到t的次数,然后在比较s和t求出最后 ...

  8. HDU-2476 String painter 区间DP

    题意:给你一个长度相等的A串和B串,每次可以把一个连续的区间刷成一个字母,问从A串到B串的最少操作数. 解法:虽然这类题一看到就知道是区间DP,但是之前只做过类似从空串变成某个串的题目,所以没想到怎么 ...

  9. HDU 2476 String painter (区间DP)

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

最新文章

  1. 成功有感之给年轻人的10个忠告
  2. python 压缩文件(1)
  3. [游戏引擎中文版]YU-RIS 4.5 最新中文支持版
  4. 接受数据,table列表,外加判断
  5. 母版页调用内容页的方法的简单实现
  6. 如何从ERP将Material的Batch信息下载到CRM
  7. 分库分表:TIDB,你是来抢生意的?不讲码德?
  8. python 正则表达式集合-抄的
  9. 格雷码Gray Code详解
  10. 计算机键盘盲打方法,电脑键盘盲打练习方法 盲打键盘指法练习技巧
  11. 激光雷达原理及发展现状
  12. 工程制图与AUTOCAD【1】
  13. vue h5分享微信节日头像合成”
  14. MySQL 官网下载地址
  15. 阿里云 验证四要素 服务
  16. springBoot打jar包遇到的麻烦
  17. 阻容感原件选择标规范
  18. iPhone7如何远程控制Linux,iPhone 7成功引导postmarketOS,首款苹果Linux智能手机
  19. rgb颜色设置方法及常用颜色的RGB值
  20. 台湾燃太TN905/TN901模块的使用及驱动程序

热门文章

  1. shell编程-变量
  2. Codeforces Round #354 (Div. 2)
  3. C#反射基础理解1(转)
  4. WCF服务实例激活类型编程与开发(转)
  5. windows mobile开发循序渐进(1)关于平台和工具
  6. 手动创建两个文本文件text1.txt和text2.txt,按要求创建text3.txt
  7. Eclipse中安装Ext插件(Spket IDE)
  8. kafka入门介绍(转载)
  9. C++走向远洋——63(项目二2、两个成员的类模板)
  10. 计算几何 - XOJ 1171 线段求交