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

1084: [SCOI2005]最大子矩阵

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 2978   Solved: 1489
[ 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

[ Submit][ Status][ Discuss]


HOME Back

这道题是简单的DP, 因为m只有2.  f[i][j][k]表示第一行前i个第二行前j个取k个的最大值. 这个可以由枚举i, j, k之后, 枚举第一行在i结尾的矩阵(就是个条), 再枚举第二行在j结尾的矩阵, 然后i==j时就结尾在i的两行的矩阵.  看看代码就懂了.

#include<stdio.h>
#include<algorithm>
using namespace std;
int n, m, K, f[105][105][11], sum[105][105];
int main(){
	scanf("%d%d%d", &n, &m, &K);
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j) scanf("%d", &sum[i][j]), sum[i][j] += sum[i - 1][j];
	if(m == 1){
		for(int i = 1; i <= n; ++i)
			for(int k = 1; k <= K && k <= i; ++k){
				f[i][0][k] = f[i - 1][0][k];
				for(int j = k - 1; j < i; ++j)
					f[i][0][k] = max(f[i][0][k], f[j][0][k - 1] + sum[i][1] - sum[j][1]);
			}
		printf("%d\n", f[n][0][K]);
	}else{
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= n; ++j)
				for(int k = 1; k <= K; ++k){
					f[i][j][k] = max(f[i - 1][j][k], f[i][j - 1][k]);
					for(int p = k-1;p < i;++p)f[i][j][k]=max(f[i][j][k], f[p][j][k - 1] + sum[i][1] - sum[p][1]);
					for(int p = k-1;p < j;++p)f[i][j][k]=max(f[i][j][k], f[i][p][k - 1] + sum[j][2] - sum[p][2]);
					if(i == j) for(int p = k - 1; p < i; ++p) f[i][j][k] = max(f[i][j][k], 
												 f[p][p][k - 1] + sum[i][1] - sum[p][1] + sum[j][2] - sum[p][2]);
				}
		printf("%d\n", f[n][n][K]);
	}	
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值