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])。

普通的循环迭代版本

 #include<bits/stdc++.h>
using namespace std;
#define debug(x) cout<<"["<<#x<<"]"<<" is "<<x<<endl;
char ch[],ch2[];
int dp[][],ans[];
const int inf=1e8;
int main(){
while(scanf("%s",ch+)!=EOF){
scanf("%s",ch2+);
int len=strlen(ch+);
for(int i=;i<=len;i++){
for(int j=;j<=len;j++){
if(i>j)dp[i][j]=;
else if(i==j)dp[i][j]=;
else dp[i][j]=inf;
}
}
for(int i=;i<=len;i++){
for(int j=;j+i-<=len;j++){
for(int k=j+;k<=j+i-;k++){
if(ch2[j]==ch2[k])dp[j][j+i-]=min(dp[j][j+i-],dp[j][k-]+dp[k+][j+i-]);
else dp[j][j+i-]=min(dp[j][j+i-],min(dp[j][k]+dp[k+][j+i-],dp[j][k-]+dp[k][j+i-]));
}
}
}
for(int i=;i<=len+;i++){
ans[i]=inf;
}
ans[]=;
for(int i=;i<=len;i++){
if(ch[i]==ch2[i]){
ans[i+]=min(ans[i+],ans[i]);
}
else{
for(int j=;j<=i;j++){
ans[i+]=min(ans[i+],ans[j]+dp[j][i]);
}
}
}
printf("%d\n",ans[len+]);
}
return ;
}

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

 #include<bits/stdc++.h>
using namespace std;
#define debug(x) cout<<"["<<#x<<"]"<<" is "<<x<<endl;
char ch[],ch2[];
int dp[][],ans[];
const int inf=1e8;
int sol(int l,int r){
if(dp[l][r]!=0x3f3f3f3f)return dp[l][r];
if(l>r)return dp[l][r]=;
if(l==r)return dp[l][r]=;
for(int k=l+;k<=r;k++){
if(ch2[k]==ch2[l]){
dp[l][r]=min(dp[l][r],sol(l+,k)+sol(k+,r));
}
else{
dp[l][r]=min(dp[l][r],sol(l+,r)+);
}
}
return dp[l][r];
}
int main(){
while(scanf("%s",ch+)!=EOF){
scanf("%s",ch2+);
int len=strlen(ch+);
memset(dp,0x3f3f3f3f,sizeof(dp));
for(int i=;i<=len;i++){
for(int j=i;j<=len;j++){
sol(i,j);
}
}
// sol(1,len);
for(int i=;i<=len+;i++){
ans[i]=0x3f3f3f3f;
}
ans[]=;
for(int i=;i<=len;i++){
if(ch[i]==ch2[i]){
ans[i+]=min(ans[i+],ans[i]);
}
else{
for(int j=;j<=i;j++){
ans[i+]=min(ans[i+],ans[j]+dp[j][i]);
}
}
}
printf("%d\n",ans[len+]);
}
return ;
}

[一道区间dp][String painter]的更多相关文章

  1. HDU 2476 区间DP String painter

    题解 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm ...

  2. 又一道区间DP的题 -- P3146 [USACO16OPEN]248

    https://www.luogu.org/problemnew/show/P3146 一道区间dp的题,以区间长度为阶段; 但由于要处理相邻的问题,就变得有点麻烦; 最开始想了一个我知道有漏洞的方程 ...

  3. 再一道区间DP -- P4170 [CQOI2007]涂色

    https://www.luogu.org/problemnew/show/P4170 一道简单的区间DP,注意读入 #include <bits/stdc++.h> #define up ...

  4. 还一道区间DP -- MZOJ 1346: 不老的传说

    http://10.37.2.111/problem.php?id=1346 与上一道染色基本一样,就加了个限制条件(一次最多刷maxd) #include <bits/stdc++.h> ...

  5. 一道区间DP的水题 -- luogu P2858 [USACO06FEB]奶牛零食Treats for the Cows

    https://www.luogu.org/problemnew/show/P2858 方程很好想,关键我多枚举了一次(不过也没多大关系) #include <bits/stdc++.h> ...

  6. 区间dp的典例

    区间dp, 属于dp的一种,顾名思义,便是对区间处理的dp,其中石子归并,括号匹配,整数划分最为典型. (1)石子归并 dp三要素:阶段,状态,决策. 首先我们从第i堆石子到第j堆石子合并所花费的最小 ...

  7. HDU4632:Palindrome subsequence(区间DP)

    Problem Description In mathematics, a subsequence is a sequence that can be derived from another seq ...

  8. POJ2955:Brackets(区间DP)

    Description We give the following inductive definition of a “regular brackets” sequence: the empty s ...

  9. POJ1179Polygon(区间dp)

    啊~~ 被dp摁在地上摩擦的人 今天做了一道区间dp的题(POJ1179Polygon) 题目: Polygon Time Limit: 1000MS   Memory Limit: 10000K T ...

随机推荐

  1. Python基础运算符(算数、比较、赋值、逻辑、成员)

    Python运算符有(算数运算符.比较运算符.赋值运算符.逻辑运算符.位运算符.成员运算符.身份运算符): 本程序包含算数.比较.赋值.逻辑.成员运算符. 1.运算符测试 #!/usr/bin/pyt ...

  2. Python笔记day20-面向对象

    目录 面向对象 1 装饰器 1.1 装饰器是什么? 1.2 装饰器 2 面向对象 (Object Oriented) 简称OO 2.1 面向对象相关术语 2.2 类和对象 2.3 类和对象的实现和书写 ...

  3. PAT(B) 1017 A除以B(Java)

    题目链接:1017 A除以B 分析 读取输入的A和B后,保存为字符串.模拟除法运算过程. 不要用BigInteger,因为会超时. 另外字符串经常要扩展(例如:append())的话,不要用Strin ...

  4. 跟我一起学编程—《Scratch编程》第24课:幸运大转盘

    同学你好,欢迎来到<跟我一起学编程>,我是包老师.这是<Scratch3.0编程>课程的第24课,我这节课教你做一个抽奖游戏:幸运大转盘. 学习目标: 1. 能够熟练使用造型工 ...

  5. vuex 理解

    为什么要用vuex?页面由多个视图组成,用户操作会引视图的状态变化. 多个视图依赖于同一状态(例如:菜单导航) 来自不同视图的行为需要变更同一状态(例如:评论弹幕) vuex 的作用 为vue.js开 ...

  6. Largest Submatrix 3 CodeForces - 407D (dp,好题)

    大意: 给定矩阵, 求选出一个最大矩形, 满足矩形内每个元素互不相同. 考虑枚举上下左三个边界, 求出最大右边界的位置. 注意到固定上边界, 下边界递推时, 每个左边界对应最大右边界是单调不增的. 所 ...

  7. (五)mybatis之一对一关系

    一.需求分析 需求:查询订单信息关联查询用户信息 分析:一条订单只能由一个消费者来下单,也就是说从订单的角度来说与消费者是一对一的关系. 二.建数据库表和实体对象 其中订单表中的字段user_id对应 ...

  8. 在.netcore webapi项目中使用后台任务工具Hangfire

    安装Hangfire 在webapi项目中通过nuget安装Hangfire.Core,Hangfire.SqlServer,Hangfire.AspNetCore,截止到目前的最新版本是1.7.6. ...

  9. 博客自定义1-皮肤模板 基于SimpleMemory 添加到顶部小按钮

    周五公司事不是很紧,打算好好弄下自己的博客,这是自己学习和记录分享地方, 首先请记得申请js权限,默认不支持的,博主是已经申请通过后的样子 接着先选择cnblogs一个现有的模板,我这个就是在他的模板 ...

  10. 如何在含有json类型的字段上建立多列索引

    废话不多,直接上图 如 : 表结构如图           那么我想在这三个字段上建立一个唯一索引,目的是为了防止重复插入数据, 1.首先,说明一下 data中的json中,key为 tagID 和 ...