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

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

然后发生了什么吗大家都应该猜到啦!然后一读题,让你求出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 ; }