【2014广州市选day1】字符串距离题解

Description

给出两个由小写字母组成的字符串 X 和Y ,我们需要算出两个字符串的距离,定义如下:
1)我们可以在字符串的头、尾、中间插入若干空格,组成一个新的扩展串
2)对X扩展成扩展串X1,对Y扩展成扩展串Y1,并且令X1和Y1具有相同的长度
3)定义X1、Y1的距离为每个对应的字符的距离之和,其中两个空格的距离为0,两个非空格字符的距离为其ASCII码之差的绝对值,一个空格字符到任意非空格字符的距离为K
4)对于字符串X、Y,必然存在两个等长的扩展串X1、Y1,使得X1、Y1的距离达到最少,我们将这一距离定义为字符串X、Y的距离

Solution

经过观察可以发现,其实我们并不需要在乎两个字符串经过任意操作后的长度是否相等(我们可以用空格把它们填满),我们只在乎两个字符串谁和谁匹配,所以可以想到dp。
f[i][j]f[i][j]f[i][j]表示字符串X的第i个字符和字符串Y的第j个字符匹配,包括了前面的匹配的最小代价。
状态转移方程:f[i][j]=min(f[i][j],f[i1][j1]+dis(i,j)+(i−i1+j−j1)∗k)f[i][j]=min(f[i][j],f[i1][j1]+dis(i,j)+(i-i1+j-j1)*k)f[i][j]=min(f[i][j],f[i1][j1]+dis(i,j)+(ii1+jj1)k)
解释一下,其中的dis(i,j)dis(i,j)dis(i,j)表示第i个字符和第j个字符的距离,而其中的(i−i1+j−j1)∗k(i-i1+j-j1)*k(ii1+jj1)k表示i1+1i1+1i1+1iiij1+1j1+1j1+1jjj的字符串都与空格匹配。这样做是正确的,我们可以不断地给中间增加空格让这些字符都与空格匹配。
最后统计答案的时候就找到一对匹配,让后面的字符全部与空格匹配就行了。很容易打。

Code

#include<cstdio>
#include<algorithm>
#define RE register
#define fo(x,a,b) for(RE int x=a;x<=b;++x)
using namespace std;
int k,ans=0x7f7f7f7f;
int a[2][31],f[31][31];
inline void read(int x) {
	char ch=getchar();
	while(ch<'a'||ch>'z')ch=getchar();
	while(ch>='a'&&ch<='z')
		a[x][++a[x][0]]=ch,ch=getchar();
}
int main() {
	freopen("distance.in","r",stdin);
	freopen("distance.out","w",stdout);
	read(0);read(1);
	scanf("%d",&k);
	for(register int i=1;i<=a[0][0];++i)
		for(register int j=1;j<=a[1][0];++j) {
			f[i][j]=abs(a[0][i]-a[1][j])+(i+j-2)*k;
			for(register int l=1;l<i;++l)
				for(register int r=1;r<j;++r)
					f[i][j]=min(f[i][j],f[l][r]+abs(a[0][i]-a[1][j])+(i-l+j-r-2)*k);
			ans=min(ans,f[i][j]+(a[0][0]-i+a[1][0]-j)*k);
		}
	printf("%d",ans);
	fclose(stdin);
	fclose(stdout);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值