码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ 1068] [SCOI2007] 压缩 【区间 DP 】

时间:2015-01-31 09:25:15      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:BZOJ - 1068

 

题目分析

这种区间 DP 之前就做过类似的,也是字符串压缩问题,不过这道题稍微复杂一些。

需要注意如果某一段是 S1S1 重复,那么可以变成 M + Solve(S1) + R ,不过这个 Solve(S1) 中不能在中间有 M ,否则后面的 R 向前找到的 M 就不再是开头的 M 了。

 

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>

using namespace std;

const int MaxL = 50 + 5;

int l, Ans;
int g[MaxL][MaxL][3];

char S[MaxL];

bool Check(int l, int r) {
	if ((r - l + 1) & 1) return false;
	int mid = (l + r) >> 1, t = (r - l + 1) >> 1;
	for (int i = l; i <= mid; ++i) 
		if (S[i] != S[i + t]) return false;
	return true;
}

int Solve(int l, int r, int f) {
	if (g[l][r][f] > 0) return g[l][r][f];
	int ret = r - l + 1, t;
	if (Check(l, r)) {
		t = Solve(l, l + ((r - l) / 2), 2);
		++t; //R
		if (f == 0) ++t; //M
		if (ret > t) ret = t;
 	}
	for (int i = l; i <= r - 1; ++i) {
		if (f != 2) t = Solve(l, i, f) + Solve(i + 1, r, 0);
		else t = Solve(l, i, 2) + (r - i);
		if (ret > t) ret = t;
 	}
	g[l][r][f] = ret;
	return ret;
}

int main() 
{
	scanf("%s", S + 1);
	l = strlen(S + 1);
	Ans = Solve(1, l, 1);
	printf("%d\n", Ans);
	return 0;
}

  

[BZOJ 1068] [SCOI2007] 压缩 【区间 DP 】

标签:

原文地址:http://www.cnblogs.com/JoeFan/p/4263614.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!