最少操作数

//整体的思路:
//先知道1-i刷成b最少需要多少次
//然后知道
//dp数组提供了任意区间由A转换成B的最小次数
//f数组实际考虑b的情况来决定是否采用dp提供的数据
//dp数组:提供任意区间 [i, j] 的局部最优解,不考虑全局情况。
//f数组:在全局范围内优化,决定是否采用 dp 提供的局部最优解,同时考虑分段优化和已满足条件的字符。
//f数组的存在是为了将 dp 数组的局部最优解整合到全局最优解中,进一步优化最终结果。
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e2+9;
ll dp[N][N],f[N];
char a[N],b[N];
//dp[i][j]的含义:从i-j区间内刷成b需要的最小次数 dp表示一个局部的最优解
//f[i]表示从1刷到i的代价  表示一个全部的最优解
int main()
{
  cin>>a+1>>b+1;
  int n=strlen(a+1);
  memset(dp,0x3f,sizeof(dp));//初始化为最大值
  for(int i=1;i<=n;i++ ) dp[i][i]=1;
  //区间DP 求1-i刷成b需要最少需要多少次
  for(int len=2;len<=n;len++)
  {
    for(int l=1;l+len-1<=n;l++)
    {
      int r = len + l -1 ;
      //这里就是刷成b需要多少次
      if(b[l]==b[r])dp[l][r]=min(dp[l+1][r],dp[l][r-1]);
      //这里为什么是b不是a需要好好的体会一下
      //如果两个端点相等就可以连带一起刷上
      for(int k=l;k<r;k++)
      {
        dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]);
      }
    }
  }//字符串A和B的理解
  //B就是目标的样子,A就是现在的状况,“B在时间上是A的继承样子”
  for(int i=1;i<=n;i++) f[i]=dp[1][i]; //默认全部需要刷,不存在相等的位置
  //但实际上存在一些地方有相同之处,所以要讨论
  for(int i=1;i<=n;i++)//右端点从1到n进行遍历
  {
    if(a[i]==b[i]) f[i]=min(f[i],f[i-1]);
    for(int j=1;j<i;j++) f[i]=min(f[i],f[j]+dp[j+1][i]);
    //应该还是插点,这里的j相当于k,因为左端点定了.
    //从j+1-i的区间不刷,从1-j的区间可能刷,也可能不刷
  }
  cout<<f[n]<<endl;
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值