zoukankan      html  css  js  c++  java
  • hdu2476(区间dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2476

    题意:给出两个字符串str1, str2,每次操作都可以将任意区间所有字符改成某个字符,问最少需要几次操作可以将字符串str1变成str2;

    思路:区间dp

    写过一道和本题很像的题目:http://www.cnblogs.com/geloutingyu/p/6597111.html

    这道题求的是将一个空串变成目标串最少需要几次操作;

    对于本题,不妨先求出由空串变成str2至少需要几次操作,再拿str1去匹配。

    假设已经求得dp[i][j]为空串变成str[i, j]需要的最少操作次数(关于如何求dp可以看我前面给出的那篇博客);

    用ans[i]存储区间[0, i]中str1变成str2最少需要的操作次数,显然初始化为ans[i]=dp[0][i],str1变成str2需要的操作肯定不会比空串多;

    对于当前字符,若str1[i]==str2[i],那么当前字符不需要再涂抹,所以有ans[i]=ans[i-1];

    若str1[i]!=str2[i],区间[0, i]的子串中可能有匹配的字符,那么可以用其子串来更新当前串的解,所以可以枚举一个中间字符 j,则有:

    ans[i]=min(ans[i], ans[j]+dp[j+1][i])

    代码:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #define MAXN 110
     5 using namespace std;
     6 
     7 char str1[MAXN], str2[MAXN];
     8 int dp[MAXN][MAXN];//dp[i][j]存储从空白得到str2[i,j]至少要涂抹多少次
     9 int ans[MAXN];//ans[1]存储区间[0,i]str1,str2匹配最少需要涂抹的次数
    10 
    11 int main(void){
    12     while(~scanf("%s%s", str1, str2)){
    13         memset(dp, 0, sizeof(dp));
    14         memset(ans, 0, sizeof(ans));
    15         int len=strlen(str2);
    16         for(int i=0; i<len; i++){//i为尾字符
    17             for(int j=i; j>=0; j--){//i为尾字符,j为头字符
    18                 dp[j][i]=dp[j+1][i]+1;//若没有重复的字符,那么[i,j]可以由[i+1,j]+1得到
    19                 for(int k=j+1; k<=i; k++){
    20                     if(str2[k]==str2[j]){//枚举中间字符,若str2[k]==str2[j],则dp[i][k]==dp[i+1][k]
    21                         dp[j][i]=min(dp[j][i], dp[j+1][k]+dp[k+1][i]);
    22                     }
    23                 }
    24             }
    25         }
    26         for(int i=0; i<len; i++){//初始化ans数组
    27             ans[i]=dp[0][i];
    28         }
    29         for(int i=0; i<len; i++){
    30             if(str2[i]==str1[i]){//若当前字符相同,则不需要涂抹
    31                 if(!i){
    32                     ans[i]=0;
    33                 }else{
    34                     ans[i]=ans[i-1];
    35                 }
    36             }else{//若前字符不同则通过其子串更新当前字符串使解最优
    37                 for(int j=0; j<=i; j++){
    38                     ans[i]=min(ans[i], ans[j]+dp[j+1][i]);
    39                 }
    40             }
    41         }
    42         printf("%d
    ", ans[len-1]);
    43     }
    44     return 0;
    45 }
    View Code
  • 相关阅读:
    树状数组入门讲解
    注册鼠标右键
    马踏棋盘问题
    先有鸡还是先有蛋
    使用Python-OpenCV向图片添加噪声(高斯噪声、椒盐噪声)
    灰值形态学中的腐蚀与膨胀
    Python-OpenCV——Morphological Transformations(形态学转换)
    Python-OpenCV——Image inverting
    Python-OpenCV中的cv2.inpaint()函数
    UML类图几种关系的总结
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/6601713.html
Copyright © 2011-2022 走看看