POJ 1390 Blocks(区间DP)

Blocks

【题目链接】Blocks

【题目类型】区间DP

&题意:

给定n个不同颜色的盒子,连续的相同颜色的k个盒子可以拿走,权值为k*k,求把所有盒子拿完的最大权值

&题解:

这题是在16北大集训的pdf看见的,听说黑书上也有.它的那个多加一维真的很难想,dp方程现在也没怎么懂,先记一下吧,以后回来认真补

&代码:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int M = 210;
struct Segment {
	int color;
	int len;
};
Segment segments[M];
int score[M][M][M];

int ClickBox(int i, int j, int len) {
	if(score[i][j][len] != -1)
		return score[i][j][len];
	int result = (segments[j].len + len) * (segments[j].len + len);
	if(i == j) {
		return result;
	}
	result += ClickBox(i, j - 1, 0);
	for(int k = i; k <= j - 1; k++) {
		if(segments[k].color != segments[j].color)
			continue;
		int r = ClickBox(k + 1, j - 1, 0);
		r += ClickBox(i, k, segments[j].len + len);
		result = max(result, r);
	}
	return score[i][j][len] = result;
}

int main() {
	freopen("E:1.in", "r", stdin);
	int T;
	cin >> T;
	for(int t = 1; t <= T; ++t) {
		int n;
		memset(score, -1, sizeof(score));
		cin >> n;
		int lastC = 0;
		int segNum = -1;
		for(int i = 0; i < n; i++) {
			int c;
			cin >> c;
			if(c != lastC) {
				segNum++;
				segments[segNum].len = 1;
				segments[segNum].color = c;
				lastC = c;
			}
			else {
				segments[segNum].len++;
			}
		}
		cout << "Case " << t << ": " << ClickBox(0, segNum, 0) << endl;
	}
}
原文地址:https://www.cnblogs.com/s1124yy/p/7149924.html