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

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;
}

 

posted @ 2018-08-21 18:58  Sugewud  阅读(313)  评论(0编辑  收藏  举报