P2453-最短距离(DP)

题意:

源串中的单个字符可被删除(delete);

被替换 (replace);

被复制到目标串中去(copy);

字符也可被插入(insert);

源串中的两个相邻字符可进行交换并复制到目标串中去(twiddle);

在完成其它所有操作之后,源串中余下的全部后缀就可用删至行末的操作删除(kill)。

操作delete,replace,copy,insert,twiddle和kill中每一个都有一个相联系的代价cost。
例如:
cost(delete)=3;
cost(replace)=6;
cost(copy)=5;
cost(insert)=4;
cost(twiddle)=4;
cost(kill)=被删除的串长*cost(delete)-1;
题解:

还是很容易知道这是dp的,设 d p [ i ] [ j ] dp[i][j] dp[i][j]为目标串匹配了前i个,源串删除了j个字符的最小价值。
讲解放在代码里好看一些…👇


AC代码:

#include<bits/stdc++.h>
using namespace std;
const int MOD = 1e9+7;
char s1[205],s2[205];
int dp[205][205];
int del,rep,cop,ins,tri;
int main(){
    ios::sync_with_stdio(false);
    //freopen("C:\\Users\\Administrator\\Desktop0\\in.txt",",r",stdin);
    memset(dp,0x7f,sizeof(dp));
    cin>>(s1+1)>>(s2+1);
    dp[0][0] = 0;
    cin>>del>>rep>>cop>>ins>>tri;
    int len1 = strlen(s1+1),len2 = strlen(s2+1);
    for(int i=1;i<=len2;i++) dp[i][0] = i*ins;//源串没有字符,只能选择添加 
    for(int i=1;i<=len1;i++) dp[0][i] = i*del;//目标串没有字符,只能选择把源串全部删掉
    for(int i=1;i<=len2;i++){
        for(int j=1;j<=len1;j++){
            dp[i][j] = min(dp[i][j],dp[i][j-1]+del);//删除源串
            dp[i][j] = min(dp[i][j],dp[i-1][j-1]+rep);//把源串字符删了,目标串添加一个
            if(s2[i] == s1[j]) dp[i][j] = min(dp[i][j],dp[i-1][j-1]+cop);
            //如果相等才能进行copy操作,也是相当于删一个源串字符,加一个目标串字符
            dp[i][j] = min(dp[i][j],dp[i-1][j]+ins);//给目标串加一个字符
            if(i-1>=1 && j-1>=1 && s2[i-1]==s1[j] && s2[i]==s1[j-1])
                dp[i][j] = min(dp[i][j],dp[i-2][j-2]+tri);
            //把源串的两个字符反转后放入目标串
            //判断一下反转以后是否一样就好
        }
    }
    int res = 0x7ffffff;
    for(int i=1;i<len1;i++)
        res = min(res,dp[len2][i]+(len1-i)*del-1);//最后要把源串字符全删
    res = min(res,dp[len2][len1]);
    cout<<res<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值