zoukankan      html  css  js  c++  java
  • hdu 2476 题解

    题目

    题意

    给出两个字符串 $ s1,s2 $,每次操作可以使一段连续的子串全变成一个字母,问最少多少次操作可以使 $ s1 $ 变为 $ s2 $.

    例如 $ zzzzzfzzzzz $,长度为 $ 11 $ ,我们就将下标看做 $ 1~11 $

    先将 $ 1-11 $ 刷一次,变成 $ aaaaaaaaaaa $

    $ 2-10:abbbbbbbbba $

    $ 2-8:abcccccccba $

    $ 3-7:abcdddddcba $

    $ 4-6:abcdeeedcab $

    $ 5:abcdefedcab $

    这样就 $ 6 $ 次,变成了 $ s2 $ 串了

    第一眼看到这题,我就想到了这个

    题意给出一个字符串,要求将一块空白木板刷成指定字符串,问最少操作次数(规则如上

    我们可以定义 $ f[i][j] $ 表示从 $ i $ 刷到 $ j $ 的最少操作次数

    转移方程

    $ f[i][j]=f[i+1][j]+1 $

    $ if(s1[i]==s1[k]) f[i][j]=min(f[i][j],f[i+1][j]+f[k+1][j]) $

    $ i+1<=k>=j $

    代码

    #include<bits/stdc++.h>
    using namespace std;
    char str1[105];
    int dp[105][105],ans[105];
    int main(){
    	scanf("%s",str1+1);
    	int n=strlen(str1+1);
    	memset(dp,0,sizeof(dp));
    	for(int j=1;j<=n;++j){//枚举终点
    		for(int i=j;i;--i){//起点
    			dp[i][j]=dp[i+1][j]+1;//直接刷
    			for(int k=i+1;k<=j;++k){
    				if(str1[i]==str1[k]){//相同就枚举断点
    					dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]);
    				}
    			}
    		}
    	}
    	printf("%d",dp[1][n]);
    	return 0;
    } 
    

    仔细一想我们可以发现如果 $ s1,s2 $ 没有一个相同的字母那么不就是上面那题吗?

    我们可以很容易发现,如果有相同字母那么就有可能缩小次数。

    我们可以定义 $ f[i][j] $ 意义同上 $ ans[i] $ 表示到第 $ i $ 个字母所需要的最少次数

    $ f $ 转移方程同上

    $ if(str1[i]==str2[i]) ans[i]=ans[i-1] $ 字母相同直接转移

    $ else ans[i]=min(ans[i],ans[j]+dp[j+1][i]) $ 字母不同考虑改变

    $ 1<j<i $

    代码

    #include<bits/stdc++.h>
    using namespace std;
    char str1[105];
    char str2[105];
    int dp[105][105],ans[105];
    int main(){
    	while(~scanf("%s %s",str1+1,str2+1)){
    		int n=strlen(str1+1);
    		memset(dp,0,sizeof(dp));
    		for(int j=1;j<=n;++j){
    			for(int i=j;i;--i){
    				dp[i][j]=dp[i+1][j]+1;
    				for(int k=i+1;k<=j;++k){
    					if(str2[i]==str2[k]){
    						dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]);
    					}
    				}
    			}
    		}
    		for(int i=1;i<=n;++i) ans[i]=dp[1][i];
    		for(int i=1;i<=n;++i){
    			if(str1[i]==str2[i]) ans[i]=ans[i-1];
    			else{
    				for(int j=1;j<i;++j){
    					ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
    				}
    			} 
    		}
    		printf("%d
    ",ans[n]);
    	}
    	return 0;
    } 
    
  • 相关阅读:
    Unity3D中的Attribute详解(二)
    Unity3D中的Attribute详解(三)
    利用TortoiseGit对Coding项目进行版本管理
    access 标准表达式中数据类型不匹配 (20091204 15:14:40)
    发布网站失败,提示一个用户控件同时存在于C盘的两个dll中
    取出被正则表达式匹配的值
    Asp.net(C#)数据绑定格式化(转)
    一个关于 asp.net 的简单问题
    ckeditor + ckfinder 上传图片的配置
    [原]可定义的英文小日历
  • 原文地址:https://www.cnblogs.com/donkey2603089141/p/11739899.html
Copyright © 2011-2022 走看看