Problem 1005 - 跳舞毯
/*zyf不小心得了一种怪病,为了维持一天的精力他必须不停跳动。于是他买了一条跳舞毯,每天跳上几小时。众所周知,跳舞毯是给定一个序列,让你在指定时间踏指定的按钮,但zyf似乎不怎么擅长,为此他写了个外挂,以修改它的输入序列,得到满分!
这个外挂的厉害之处在于它能等到zyf跳完、输入序列后再进行修改,修改的方式有三种,在任意位置插入、删除或替换一个指令,每次插入需要a时间,删除需要b时间,替换需要c时间,现在zyf想用最短时间去修改他输入的序列得到满分(即与给定序列一样),但这显然已经超过了当前外挂的能力范围,于是只好求助于你,给这外挂写个补丁。
Input
输入包含多组数据,EOF结束。
每组数据包括三行,第一行包含三个整数a,b,c(0<a,b,c<=100),如上文描述,第二行是跳舞毯给定的序列,第三行是zyf跳完、输入的序列,两者的长度都不大于1000,只包含大小写字母。
Output
每组数据输出一行,最少修改时间。
Sample Input
1 2 3
LDDD
DDDR
7 1 3
LDDR
LZRZDD
Sample Output
3
8
*/
经典dp 最长公共子序列(LCS)的变体,思路相似,dp问题注意边界。WA了无数次……第一次写dp,只是一个小错误卡了半天,我还以为是比较大小错了呢。。。
#include<stdio.h>
#include<string.h>
int f[1010][1010];
char s1[1010],s2[1010];
int a,b,c;
int cals()
{
int len1,len2,i,j,t;
len1=strlen(s1);
len2=strlen(s2);
for(i=0;i<=len1;i++) f[i][0]=i*a; //注意边界
for(j=0;j<=len2;j++) f[0][j]=j*b;
for(i=1;i<=len1;i++) //这里从1到len,当时没写等号
{
for(j=1;j<=len2;j++)
{
if(s1[i-1]==s2[j-1]) f[i][j]=f[i-1][j-1]; //注意是s1[i-1]==s2[j-1],因为i,j都从1开始。
else
{
t=((f[i][j-1]+b)<(f[i-1][j]+a))?(f[i][j-1]+b):(f[i-1][j]+a);
f[i][j]=(t<f[i-1][j-1]+c)?t:f[i-1][j-1]+c;
}
}
}
return f[len1][len2]; //返回值
}
int main()
{
while(scanf("%d%d%d%s%s",&a,&b,&c,s1,s2)!=EOF)
{
printf("%d\n",cals());
}
return 0;
}