题目
题目链接
终于开始写题目了,这个周末算是混过去了
周六睡,和学长踢球,以后每周都去中苑踢球了,那个草舒服
周日睡,参加英语竞赛,太难了(不过我感觉还能对不少,不过和我竞争还有英语专业的大四学姐)
于是我权当去玩了,提前交卷走了,不期待拿奖(结果后天就出来了😅)
然后我就写了这道题目,反正也不会,就是感叹一下写题解的人真的很厉害
思路
思路如下:
一、定义状态:
dp数组为dp[i][j]表示将A的前i个元素变成B的前j个元素的最少步数
二、状态转移方程:
对于某一个状态,我们有如下几种可能:
1.删除:
dp[i][j]=dp[i-1][j]+1
我们只解释这个
这样的状态转移子方程的含义就是说
如果利用删除的方法,dp[i][j]就是只需要A的前i-1个和B的前j个一样(最少步数)
然后我们直接删除A中的第i个即可,然后步数加1就行了
2.插入
dp[i][j]=dp[i][j-1]+1
3.改写
dp[i][j]=dp[i-1][j-1]+1
4.完全相同
dp[i][j]=dp[i-1][j-1]
(3.4可以和并在一起)
然后最后这四个取最小的
代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
char A[2002],B[2002];
int lenA,lenB;
int dp[2002][2002];
int func(int i, int j){
if(dp[i][j]){
return dp[i][j];
}
if(i==0){
dp[i][j]=j;
return dp[i][j];
}
if(j==0){
dp[i][j]=i;
return dp[i][j];
}
else{
int bonus=1;
if(A[i]==B[j]){
bonus=0;
}
dp[i][j]=min(min(func(i-1,j)+1,func(i,j-1)+1),func(i-1,j-1)+bonus);
}
return dp[i][j];
}
int main(){
scanf("%s",A+1);
scanf("%s",B+1);
for(int i=1;A[i]!='\0';i++){
lenA=i;
}
for(int i=1;B[i]!='\0';i++){
lenB=i;
}
int ans;
ans=func(lenA,lenB);
cout<<ans;
return 0;
}