题目大意就是给两个长度相同的字符串,每次操作能使一段变成相同的一个字符,要求是串1变成串2的最小操作数目
(先假设从一个完全不相同的字符串变成串2)先用区间dp求出任意两点之间的最小操作数,dp[i][j]是i到j 的最小操作数
然后用一个数组求串1到串2的最小操作数,对于某一点,如果s[i]==p[i],那么这个点不用操作,如果不相同,就从起点开始对a[i]更新一遍
转移方程a[i]=min(a[i],a[j]+dp[j+1][i]);如果有某个点j小于i,从j开始刷到i加上a【j】最小,那么就是a【i】
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-7; const int N=100+10,maxn=60000+10,inf=0x3f3f3f; int dp[N][N],a[N]; int main() { ios::sync_with_stdio(false); cin.tie(0); string s,p; while(cin>>s>>p) { int n=s.size(); s="1"+s; p="1"+p; memset(dp,0,sizeof dp); for(int i=1;i<=n;i++)dp[i][i]=1; for(int i=n-1;i>=1;i--) { for(int j=i+1;j<=n;j++) { dp[i][j]=dp[i+1][j]+1; for(int k=i;k<j;k++) { if(p[i]==p[k+1]) dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]); } } } for(int i=1;i<=n;i++) { a[i]=dp[1][i]; if(s[i]==p[i]) { if(i==1)a[i]=0; else a[i]=a[i-1]; } else { for(int j=1;j<i;j++) a[i]=min(a[i],a[j]+dp[j+1][i]); } } cout<<a[n]<<endl; } return 0; } /******************** ********************/
时间: 2024-10-12 06:41:36