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 ≤ p < a)更新

#include<bits/stdc++.h>

using namespace std;

const int maxk = 19;
const int maxn = 109;

int N, K;

namespace one {
	int sum[maxn], dp[maxn][maxk];
	void init() {
		sum[0] = 0;
		for(int i = 1; i <= N; i++) {
		    scanf("%d", sum + i);
		    sum[i] += sum[i - 1];
		}
	}
	void work() {
		init();
		memset(dp, 0, sizeof dp);
		for(int i = 0; i < N; i++) {
			for(int k = 0; k <= K; k++)
			    dp[i + 1][k] = max(dp[i + 1][k], dp[i][k]);
			for(int k = 1; k <= K; k++)
			    for(int j = i + 1; j <= N; j++)
			        dp[j][k] = max(dp[j][k], dp[i][k - 1] + sum[j] - sum[i]);
		}
		printf("%d\n", dp[N][K]);
	}
}

namespace two {
	int sum[2][maxn], dp[maxn][maxn][maxk];
	void init() {
		sum[0][0] = sum[1][0] = 0;
		for(int j = 1; j <= N; j++)
		    for(int i = 0; i < 2; i++) {
		    	scanf("%d", &sum[i][j]);
		    	sum[i][j] += sum[i][j - 1];
		    }
	}
	void work() {
		init();
		memset(dp, 0, sizeof dp);
		for(int i = 0; i <= N; i++)
	        for(int j = 0; j <= N; j++) if(i + j < N * 2) {
	            for(int k = 0; k <= K; k++) {
	            	if(i < N) dp[i + 1][j][k] = max(dp[i + 1][j][k], dp[i][j][k]);
	            	if(j < N) dp[i][j + 1][k] = max(dp[i][j + 1][k], dp[i][j][k]);
	            }
	            for(int k = 1; k <= K; k++)
	                for(int _i = i; _i <= N; _i++)
	                    for(int _j = j; _j <= N; _j++) if(_i + _j > i + j) {
	                        dp[_i][_j][k] = max(dp[_i][_j][k], dp[i][_j][k - 1] + sum[0][_i] - sum[0][i]);
	                        dp[_i][_j][k] = max(dp[_i][_j][k], dp[_i][j][k - 1] + sum[1][_j] - sum[1][j]);
	                    }
	            if(i == j) {
	            	for(int k = 0; k <= K; k++)
	            	    dp[i + 1][j + 1][k] = max(dp[i + 1][j + 1][k], dp[i][j][k]);
	            	for(int _i = i + 1; _i <= N; _i++)
	            	    for(int k = 1; k <= K; k++)
	            	        dp[_i][_i][k] = max(dp[_i][_i][k], dp[i][j][k - 1] + sum[0][_i] - sum[0][i] + sum[1][_i] - sum[1][j]);
	            }
	        }
	    printf("%d\n", dp[N][N][K]);
	}
}

int main() {

	int m;
	cin >> N >> m >> K;
	m == 1 ? one::work() : two::work();

	return 0;
}

  

1084: [SCOI2005]最大子矩阵

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1614  Solved: 821
[Submit][Status][Discuss]

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

时间: 2024-10-16 00:17:50

BZOJ 1084: [SCOI2005]最大子矩阵( dp )的相关文章

[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】

题目链接: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 个矩形的最优值. 首先

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

题目大意:给出一个矩阵,求在这个矩阵中取出k个不重叠的矩阵的最大和. 思路:怎么做? 这个问题困扰我好几天的时间,终于再一次读题: ... .. ... 2??!! 这尼玛逗我??直接说最多两列不好么?还用矩阵吓唬我? 好吧下次我一定认真看题.. 我的做法比较渣,算出来的时间复杂度是O(m^3*k),但是只有最多3000w,还是可以过的. 状态:f[i][j][k]表示第一列到了第i个格子,第二列到了第j个格子,已经选取了k个矩阵的最大得数. 转移:先把现有的状态向后转移,转移成f[i'][j'

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 1088: [SCOI2005]扫雷Mine (DP)

Bzoj 1088: [SCOI2005]扫雷Mine 怒写一发,算不上DP的游戏题 知道了前\(i-1\)项,第\(i\)项会被第二列的第\(i-1\)得知 设\(f[i]\)为第一列的第\(i\)行位置是否有雷,有雷的话,\(f[i] = 1\),无雷\(f[i] = 0\) \(a[i]\)就是题目读入的东西. 那么转移方程就是\(f[i] = a[i - 1] - f[i - 1] - f[i - 2]\) 不满足限制的时候就是\(f[i] < 0\) 或者$ f[i] > 1$ 第一

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 思路 看到题目:好难啊..一点思路都没有.

[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 题解: