每日一题 [SCOI2005]最大子矩阵 (多维dp)
[SCOI2005]最大子矩阵
https://ac.nowcoder.com/acm/problem/20242
一.题意
n * m 的矩阵分成 k 组互不重叠的矩阵,求最大的子矩阵和。
二.题解
特别注意到的是 m 的值为 1 或者 2,所以可以由比较简单的方法写出。
考虑 代表第一列前 i 个元素和第二列前 j 个元素组成 k 个矩阵的最大值。
有以下的递推方程:
- 由前一状态推出,
- 枚举第一列,
- 枚举第二列,
- 当第一列和第二列取同样多的元素可以考虑合并,
三.代码:
#include<bits/stdc++.h> #define mp make_pair #define pb push_back #define ld long double #define ll long long #define ull unsigned long long #define fi first #define se second #define inf 0x3f3f3f3f #define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) using namespace std; const int manx=1e6+5; const int N=1e3+5; const int mod=1e9+7; ll s[N][3],dp[N][N][15]; ll n,m,ans,k,x; int main(){ io; cin>>n>>m>>k; ll K=k; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>x,s[i][j]=s[i-1][j]+x; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=1;k<=K;k++){ dp[i][j][k]=max(dp[i-1][j][k],dp[i][j-1][k]); for(int l=0;l<i;l++) dp[i][j][k]=max(dp[i][j][k],dp[l][j][k-1]+s[i][1]-s[l][1]); for(int l=0;l<j;l++) dp[i][j][k]=max(dp[i][j][k],dp[i][l][k-1]+s[j][2]-s[l][2]); if(i==j) for(int l=0;l<i;l++) dp[i][j][k]=max(dp[i][j][k],dp[l][l][k-1]+s[i][1]+s[j][2]-s[l][1]-s[l][2]); } cout<<dp[n][n][K]; return 0; }