洛谷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 ;
}