洛谷P2331最大子矩阵

其实那,我是被标题吸引来的

你康康,最大子矩阵!多么人畜无害的名字啊~~~

然后发生了什么吗大家都应该猜到啦!然后一读题,让你求出k个子矩阵的最大值!

但是呢?发现这是一个n*m的矩阵废话!然后.. m = 1 或者 2 !! 你 说 话 怎 么 带 空 格 啊 啊 啊

第一种 m = 1 , 感觉很水 啊!!

你看看,不就变成了一个一维的辣!

设f[i][j] 表示 从前 i 个 数中取出j个子矩阵的最大答案

那么,就扫一遍,如果不选的话,f[i][j] = max(f[i-1][j])

选的话就是f[i][j] = max(f[0 to i][j-1] + 所选范围的和)

阶段性code

                  for(int k = 1 ; k <= K ; k ++) {
			for(int i = 1 ; i <= n ; i ++) {
				dp[i][k] = dp[i-1][k] ;
				for(int j = 0 ; j < i ; j ++) {
					dp[i][k] = max(dp[i][k],dp[j][k-1]+s1[i]-s1[j]) ;
				}
			}
		}	

下面就是m = 2 的情况啦!!!

类似的,我们设f[i][j][k] , 为 第一行 选到i , 第二行 选到 j , 一共选了k个矩阵的 最大答案

转移有4种情况

当这一位什么都不做的时候:f[i][j][k]=max(f[i-1][j][k],f[i][j-1][k])

当仅选取第一列的某段区间时:f[i][j][k]=max(f[l][j][k-1]+sum[i][1]-sum[l-1][1]) 1<=l<i

当仅选取第二列的某段区间时:f[i][j][k]=max(f[i][l][k-1]+sum[j][2]-sum[l-1][2]) 1<=l<j

当i==j时,可以选取两列一起的f[i][j][k]=max(f[l][l][k]+sum[i][1]+sum[i][2]-sum[l-1][1]-sum[l-1][2])

至于代码,就是,,


for(int k = 1 ; k <= K ; k ++) {
			for(int i = 1 ; i <= n ; i ++) {
				for(int j = 1 ; j <= n ; j ++) {
					f[i][j][k] = max(f[i-1][j][k],f[i][j-1][k]) ;
					for(int l = 0 ; l < i ; l ++) {
						f[i][j][k]=max(f[i][j][k],f[l][j][k-1]+s1[i]-s1[l]);
					}
					for(int l = 0 ; l < j ; l ++) {
						f[i][j][k]=max(f[i][j][k],f[i][l][k-1]+s2[j]-s2[l]);
					}
					if(i == j) {
						for(int l = 0 ; l < i ; l ++) {
							f[i][j][k]=max(f[i][j][k],f[l][l][k-1]+s1[i]-s1[l]+s2[j]-s2[l]);
						}
					}
				}
			}
		}

总代码

#include <bits/stdc++.h>
#define maxn 120
#define maxm 20
using namespace std ;
int n , m , K , s1[maxn] , dp[maxn][maxm] , f[maxn][maxn][maxm] , s2[maxn] ;
int main () {
	scanf("%d%d%d",&n,&m,&K) ;
	if(m == 1){
		int x ;
		for(int i = 1 ; i <= n ; i ++) {
			cin >> x ;
			s1[i] = s1[i-1] + x ; 
		}
		for(int k = 1 ; k <= K ; k ++) {
			for(int i = 1 ; i <= n ; i ++) {
				dp[i][k] = dp[i-1][k] ;
				for(int j = 0 ; j < i ; j ++) {
					dp[i][k] = max(dp[i][k],dp[j][k-1]+s1[i]-s1[j]) ;
				}
			}
		}	
		printf("%d\n",dp[n][K]) ;
	}else {
		for(int i = 1 ; i <= n ; i ++) {
			int x , y ;
			cin >> x >> y ;
			s1[i] = s1[i-1] + x ;
			s2[i] = s2[i-1] + y ;
		}
		for(int k = 1 ; k <= K ; k ++) {
			for(int i = 1 ; i <= n ; i ++) {
				for(int j = 1 ; j <= n ; j ++) {
					f[i][j][k] = max(f[i-1][j][k],f[i][j-1][k]) ;
					for(int l = 0 ; l < i ; l ++) {
						f[i][j][k]=max(f[i][j][k],f[l][j][k-1]+s1[i]-s1[l]);
					}
					for(int l = 0 ; l < j ; l ++) {
						f[i][j][k]=max(f[i][j][k],f[i][l][k-1]+s2[j]-s2[l]);
					}
					if(i == j) {
						for(int l = 0 ; l < i ; l ++) {
							f[i][j][k]=max(f[i][j][k],f[l][l][k-1]+s1[i]-s1[l]+s2[j]-s2[l]);
						}
					}
				}
			}
		}
		cout << f[n][n][K] << endl ;
	}
	return 0 ;
} 



posted @ 2019-08-20 18:47  _L_Y_T  阅读(152)  评论(0编辑  收藏  举报