*HDU2476.String painter(区间DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2476
题意:给出a和b两个字符串,目标是将a变化成b,每次变化可以将任意一段区间的字符全部涂成同一个字符,问最少的变化次数
解题思路:dp[i][j]表示a串中i到j变化成b串需要的最小次数
先在默认a和b串全部不相同的情况下,找出dp关系

for(int k=0;k<len;k++){
			for(int i=0;i+k<len;i++){
			//默认直接改变
				dp[i][i+k]=dp[i+1][i+k]+1;
				for(int j=i+1;j<=i+k;j++){
				//寻找两端相同字符的情况
					if(b[i]==b[j])
					dp[i][i+k]=min(dp[i][i+k],dp[i+1][j]+dp[j+1][i+k]);  
					//dp[i+1][j]中已经有b[i]这种,所以不需要再加上i
				}
			}
		}

然后在a字符串中具体处理,如果已存在a串与b串中某一位置相同,则不需要改变

for(int i=0;i<len;i++)  ans[i]=dp[0][i];
		for(int i=0;i<len;i++){
			if(a[i]==b[i])   //相同时,不需要再改变
				ans[i]=ans[i-1];
			else{           //不同时候,尽量往前找匹配关系
				for(int j=0;j<i;j++){
					ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
				}
			}
		}
#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
using namespace std;
#define inf 1e9
string a,b;
int dp[120][120];
int ans[120];
int len;
int min(int a,int b){
	return a<b? a:b;
}
int main(){
	while(cin>>a>>b){
		memset(dp,0,sizeof(dp));
		len=a.size();
		for(int k=0;k<len;k++){
			for(int i=0;i+k<len;i++){
				dp[i][i+k]=dp[i+1][i+k]+1;
				for(int j=i+1;j<=i+k;j++){
					if(b[i]==b[j])
					dp[i][i+k]=min(dp[i][i+k],dp[i+1][j]+dp[j+1][i+k]);  //dp[i+1][j]中已经有b[i]这种,所以不需要再加上i
				}
			}
		}
		for(int i=0;i<len;i++)  ans[i]=dp[0][i];
		for(int i=0;i<len;i++){
			if(a[i]==b[i])
				ans[i]=ans[i-1];
			else{
				for(int j=0;j<i;j++){
					ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
				}
			}
		}
		cout<<ans[len-1]<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/littlegoldgold/article/details/107372279