好久没更新牛客的博客了
更新一下下
链接:https://ac.nowcoder.com/acm/problem/20242
来源:牛客网
[SCOI2005]最大子矩阵
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。
注意:选出的k个子矩阵 不能相互重叠。
输入描述:
第一行为n,m,k(1 ≤ n ≤ 100,1 ≤ m ≤ 2,1 ≤ k ≤ 10),
接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767)。
输出描述:
只有一行为k个子矩阵分值之和最大为多少。
示例1
输入
复制
3 2 2
1 -3
2 3
-2 3
输出
复制
9
题目思路
看到这题思路是懵的。
但看一下m的范围好像就有了点起色。
当m为1时:最大k子段和
当m为2时:令第一列前i个与第二列前k个形成j个子矩阵的最大值
那么dp状态就很容易了:
可能新增的子矩阵是一列的,那么就是dp[st][k][p-1] + 第一列st~i的前缀和
如果增加第二列,与第一列同理
或者如果当i==p时此时可以将其合并
dp[st][st][p-1] + 两端前缀和
这里说一下,这么写的话无需考虑m=1或者m=2了,因为m=1时第二列全为0,对答案没有影响。
扩充一下:当m>2时可以考虑状压dp
改日补充一下 m>2的情况
/*** keep hungry and calm CoolGuang!***/ #pragma GCC optimize(2) #pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline") #include <bits/stdc++.h> #include<stdio.h> #include<queue> #include<algorithm> #include<string.h> #include<iostream> #define debug(x) cout<<#x<<":"<<x<<endl; using namespace std; typedef long long ll; typedef unsigned long long ull; const ll INF=1e18; const int maxn=1e6+6; const int mod=1e9+7; const double eps=1e-15; inline bool read(ll &num) {char in;bool IsN=false; in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;} ll n,m,p; ll num[maxn]; ll f[maxn][3]; ll mp[105][3]; ll dp1[105][105];///0/1 ll dp[105][105][105]; int main(){ read(n);read(m);read(p); for(int i=1;i<=n;i++){ for(int k=1;k<=m;k++) read(mp[i][k]); } for(int k=1;k<=m;k++){ for(int i=1;i<=n;i++){ f[i][k] = f[i-1][k] + mp[i][k]; } } ll ans = -INF; for(int i=1;i<=n;i++){ for(int k=1;k<=n;k++){ for(int j=1;j<=p;j++){ dp[i][k][j] = max(dp[i-1][k][j],dp[i][k-1][j]); for(int st=0;st<i;st++) dp[i][k][j] = max(dp[st][k][j-1]+f[i][1]-f[st][1],dp[i][k][j]); for(int st=0;st<k;st++) dp[i][k][j] = max(dp[i][st][j-1]+f[k][2]-f[st][2],dp[i][k][j]); if(i==k){ for(int st=0;st<i;st++) dp[i][k][j] = max(dp[st][st][j-1]+f[i][1]-f[st][1]+f[i][2]-f[st][2],dp[i][k][j]); } } } } for(int i=1;i<=n;i++){ for(int k=1;k<=n;k++){ ans = max(ans,dp[i][k][p]); } } printf("%lld\n",ans); return 0; } /** 3 011 100 111 **/
这个代码写的有点麻烦了,将就看吧