BZOJ 1084 SCOI2005 最大子矩阵 动态规划

题目大意:给出一个矩阵,求在这个矩阵中取出k个不重叠的矩阵的最大和。

思路:怎么做?

这个问题困扰我好几天的时间,终于再一次读题:

。。。

。。

。。。

2??!!

这尼玛逗我??直接说最多两列不好么?还用矩阵吓唬我?

好吧下次我一定认真看题。。

我的做法比较渣,算出来的时间复杂度是O(m^3*k),但是只有最多3000w,还是可以过的。

状态:f[i][j][k]表示第一列到了第i个格子,第二列到了第j个格子,已经选取了k个矩阵的最大得数。

转移:先把现有的状态向后转移,转移成f[i‘][j‘][k],然后取矩阵,向后转移,转移成f[i‘][j‘][k + 1]。这里要分三种情况讨论,转移第一列,转移第二列,和两列一起转移。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 110
using namespace std;

int m,n,c;
int src[MAX][3],sum[3][MAX];
int f[MAX][MAX][15];

int main()
{
	cin >> m >> n >> c;
	for(int i = 1; i <= m; ++i)
		for(int j = 1; j <= n; ++j) {
			scanf("%d",&src[i][j]);
			sum[j][i] = sum[j][i - 1] + src[i][j];
		}
	int ans = 0;
	if(n == 1) {
		for(int i = 0; i <= m; ++i)
			for(int k = 0; k <= c; ++k)
				for(int _i = i + 1; _i <= m; ++_i) {
					f[_i][k][0] = max(f[_i][k][0],f[i][k][0]);
					f[_i][k + 1][0] = max(f[_i][k + 1][0],f[i][k][0] + sum[1][_i] - sum[1][i]);
				}
		for(int i = 0; i <= m; ++i)
			for(int k = 0; k <= c; ++k)
				ans = max(ans,f[i][k][0]);
	}
	else {
		for(int i = 0; i <= m; ++i)
			for(int j = 0; j <= m; ++j)
				for(int k = 0; k <= c; ++k) {
					for(int _i = i + 1; _i <= m; ++_i) {
						f[_i][j][k] = max(f[_i][j][k],f[i][j][k]);
						f[_i][j][k + 1] = max(f[_i][j][k + 1],f[i][j][k] + sum[1][_i] - sum[1][i]);
					}
					for(int _j = j + 1; _j <= m; ++_j) {
						f[i][_j][k] = max(f[i][_j][k],f[i][j][k]);
						f[i][_j][k + 1] = max(f[i][_j][k + 1],f[i][j][k] + sum[2][_j] - sum[2][j]);
					}
					for(int _k = max(i,j) + 1; _k <= m; ++_k) {
						f[_k][_k][k] = max(f[_k][_k][k],f[i][j][k]);
						f[_k][_k][k + 1] = max(f[_k][_k][k + 1],f[i][j][k] + sum[1][_k] - sum[1][max(i,j)] + sum[2][_k] - sum[2][max(i,j)]);
					}
				}
		for(int i = 0; i <= m; ++i)
			for(int j = 0; j <= m; ++j)
				for(int k = 0; k <= c; ++k)
					ans = max(ans,f[i][j][k]);
	}
	cout << ans << endl;
	return 0;
}

时间: 2024-10-31 05:47:05

BZOJ 1084 SCOI2005 最大子矩阵 动态规划的相关文章

[BZOJ 1084][SCOI2005]最大子矩阵

Description 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. Input 第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767). Output 只有一行为k个子矩阵分值之和最大为多少. Sample Input 3 2 2 1 -3 2 3 -2 3 Sample Output 9 HINT Source 刚开始没看清题,以

BZOJ 1084: [SCOI2005]最大子矩阵( dp )

最多只有2列..分开来dp 1列 dp(x, k) = max( dp(x - 1, k), dp(p, k - 1) + sum(p+1~x) ) 2列 dp(a, b, k) = max( dp(a - 1, b, k), dp(a, b - 1, k), dp(p, b, k - 1) + sum1(p+1~a), dp(a, p, k - 1) + sum2(p+1~b) ) 当a = b, dp(a, b, k)还可以用dp(p, p, k - 1) + SUM(p+1~a) (0 ≤

[BZOJ 1084] [SCOI2005] 最大子矩阵 【DP】

题目链接:BZOJ - 1084 题目分析 我看的是神犇BLADEVIL的题解. 1)对于 m = 1 的情况, 首先可能不取 Map[i][1],先 f[i][k] = f[i - 1][k];  再考虑取一段新的的情况,用 max(f[j][k - 1] + Sum[i][1] - Sum[j][1])   (0 <= j < i)  更新 f[i][j]: 2) 对于 m = 2 的情况,用 f[i][j][k] 表示左列取到第 i 个,右列取到第 j 个,共 k 个矩形的最优值. 首先

1084: [SCOI2005]最大子矩阵 - BZOJ

Description 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. Input 第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767). Output 只有一行为k个子矩阵分值之和最大为多少. Sample Input 3 2 2 1 -3 2 3 -2 3 Sample Output 9 因为m≤2,所以就成了sbDP题,分情况D

1084: [SCOI2005]最大子矩阵

1084: [SCOI2005]最大子矩阵 Description 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. Input 第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767). Output 只有一行为k个子矩阵分值之和最大为多少. Sample Input 3 2 2 1 -3 2 3 -2 3 Sample Output 9

BZOJ 1084 最大子矩阵 终于过了

一开始看到这道题,由于觉得m <= 2, 所以觉得这是道水题,回去后想了一下.在晚上来机房的时候已经想出来了,但是我必须承认细节决定成败.远在一个小时前我就已经把算法的主体都写好了,但是就是一直WA,为什么就是各种粗心,真心想捏死自己.一个小时就这么白白浪费了.我希望明天的我能变得强大一点.在有了今日惨痛的教训之后. 这道题并不难.用d[i][j][k] 来表示状态.i表示第几行,j表示之前取了多少个矩阵,k表示上一行的状态.即上一行的矩阵取法.如果k == 0 那么没有一个矩阵延伸到上一行,如

【SCOI2005】 最大子矩阵 BZOJ 1084

Description 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. Input 第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767). Output 只有一行为k个子矩阵分值之和最大为多少. Sample Input 3 2 2 1 -3 2 3 -2 3 Sample Output 9 思路 看到题目:好难啊..一点思路都没有.

[BZOJ 1088][SCOI2005]扫雷Mine

Description 相信大家都玩过扫雷的游戏.那是在一个n*m的矩阵里面有一些雷,要你根据一些信息找出雷来.万圣节到了,"余"人国流行起了一种简单的扫雷游戏,这个游戏规则和扫雷一样,如果某个格子没有雷,那么它里面的数字表示和它8连通的格子里面雷的数目.现在棋盘是n×2的,第一列里面某些格子是雷,而第二列没有雷,如下图: 由于第一列的雷可能有多种方案满足第二列的数的限制,你的任务即根据第二列的信息确定第一列雷有多少种摆放方案. Input 第一行为N,第二行有N个数,依次为第二列的格

[SCOI2005] 最大子矩阵

P2331 [SCOI2005] 最大子矩阵 题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 输入格式: 第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767). 输出格式: 只有一行为k个子矩阵分值之和最大为多少. 输入输出样例 输入样例#1: 3 2 2 1 -3 2 3 -2 3 输出样例#1: 9 题解: