HDU-2476 String painter

挺有难度的一道题,区间DP,我参考别人的代码,自己加了写注释
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=100+10;
const int INF=0x7f7f7f7f;
char a[N],b[N];
int d[N][N],ans[N];
int main()
{
	while(~scanf("%s%s",a,b))
	{
		int l=strlen(b);
		memset(d,0,sizeof(d));
		for(int i=0;i<l;i++)
			d[i][i]=1;
		//先求将一个空串转换成b需要的最少步数,d[l][r]代表l~r区间
		for(int i=1;i<l;i++)
			for(int j=0;j+i<l;j++)
			{//如果左右端相同,可以开始直接将整个区间刷为一色,不需要再加一步
				d[j][j+i]=d[j+1][j+i]+(b[j]==b[j+i]?0:1); 
				for(int k=j+1;k<j+i;k++) //遍历一遍区间
					if(b[j]==b[k]) //如果和左端相同,可以考虑拆分为两个区间,可能减少步数
						d[j][j+i]=min(d[j][j+i],d[j+1][k]+d[k+1][j+i]);
			}
		//ans[i]代表将前i位a转换成b需要的步数
		ans[0]=(a[0]==b[0]?0:1); //第一位相同则ans[0]为0
		for(int i=1;i<l;i++)
		{
			ans[i]=d[0][i]; //初始值为将空串转化为b串0~i的步数
			if(a[i]==b[i]) //如果这一位相同,可以不管,是前一位的步数
				ans[i]=min(ans[i],ans[i-1]);
			for(int j=0;j<i;j++) //遍历区间0~i,考虑把前j+1~i为作为空串处理
				ans[i]=min(ans[i],ans[j]+d[j+1][i]);
		}

		printf("%d\n",ans[l-1]);
	}
	return 0;
}

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页