当前位置: 代码迷 >> 综合 >> caioj 1069 动态规划入门(二维一边推2:顺序对齐)(最长公共子序列拓展总结)
  详细解决方案

caioj 1069 动态规划入门(二维一边推2:顺序对齐)(最长公共子序列拓展总结)

热度:103   发布时间:2023-09-20 19:55:23.0

caioj 1068是最长公共子序列裸体,秒过, 就不写博客了

caioj 1069到1071 都是最长公共字序列的拓展,我总结出了一个模型,屡试不爽
   (1) 字符串下标从1开始,因为0用来表示字符为空的情况,而不是第一个字符 
   (2)初始化问题。
         一般设f[i][j]为第一个字符前i个,第二个字符前j个的最优价值
         f[0][0] = 0
          然后要初始化f[i][0], f[0][i]

      这个时候要根据题意。
         这个时候就是一个字符有,一个字符空的情况
   (3)然后就可以两层for了
          这个时候记住根据题目有不同的决策,取最优
          一般有匹配字符和不匹配字符(如加空格)两种情况

          按照题目而定  
          最后要注意如果是取min初值要最大,max初值最小
          或者直接用其中一个决策作为初值 

 

这道题要右对齐,所以直接逆序存
    
然后套模型

初始化的话,显然空的时候全部都是空格
所以都初始化为-1

决策的话
如果是匹配字符的话,一样就加2,否则不加
如果是空格的话,就两边枚举空格长度取最优

具体看代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;const int MAXN = 60;
char a[MAXN], b[MAXN], s[MAXN];
int f[MAXN][MAXN];void up(int &x, int a) { x = max(x, a); }int main()
{scanf("%s", s + 1);int lena = strlen(s + 1);REP(i, 1, lena + 1) a[i] = s[lena-i+1];scanf("%s", s + 1);int lenb = strlen(s + 1);REP(i, 1, lenb + 1) b[i] = s[lenb-i+1];REP(i, 1, lena + 1) f[i][0] = -1;REP(i, 1, lenb + 1) f[0][i] = -1;f[0][0] = 0;int ans = -1e9;REP(i, 1, lena + 1)REP(j, 1, lenb + 1){f[i][j] = -1e9; if(a[i] == b[j]) up(f[i][j], f[i-1][j-1] + 2); //选择匹配字符 else up(f[i][j], f[i-1][j-1]);for(int k = i - 1; k >= 0; k--) up(f[i][j], f[k][j] - 1); //选择空格 for(int k = j - 1; k >= 0; k--) up(f[i][j], f[i][k] - 1);up(ans, f[i][j]);}printf("%d\n", ans);return 0;
}

 

  相关解决方案