链接:
@[toc]
题目描述
这里有一个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的范围是12i-1)
当m=1时,就相当于一维数组,求最大连续k段和
dp[i][j]表示前i个位置选出j段的最大价值。
转移方程是
for(z: 1
dp[i][j]=max(dp[i-1][j],dp[z][j-1]+sum[zi])i的元素值的和
sum表示z
当m=2时,
dp[i][j][l]表示第一列的前i个数,第二列的前j个数总共选了k个子矩形的答案
sum[i][1/2]表示第1列或第二列的前缀和
(其实就是 把m=1的情况进行延伸)
当i = = j时,两列就可以拼成一个矩阵
dp[i][j][k] = max(dp[x][x][k] + sum[i][1] - sum[x-1][1] + sum[i][2] - sum[x-1][2])
仅在第一列选一个区间:
dp[i][j][k]=max(dp[x][j][k-1]+sum[i][1]-sum[x-1][1])
仅在第二列选一个区间:
dp[i][j][k]=max(dp[i][x][k-1]+sum[j][2]-sum[x-1][2])
什么都不选:
dp[i][j][k]=max(dp[i-1][j][k],dp[i][j-1][k])
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 105; int a[N][N]; int dp[N][N][20]; int sum[N][3]; int main() { int n,m,K; cin>>n>>m>>K; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ cin>>a[i][j]; sum[i][j]=sum[i-1][j]+a[i][j]; } 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 x=0;x<i;x++) dp[i][j][k]=max(dp[i][j][k],dp[x][j][k-1]+sum[i][1]-sum[x][1]); for(int x=0;x<j;x++) dp[i][j][k]=max(dp[i][j][k],dp[i][x][k-1]+sum[j][2]-sum[x][2]); if(i==j) { for(int x=0;x<i;x++) dp[i][j][k]=max(dp[i][j][k],dp[x][x][k-1]+sum[i][1]+sum[j][2]-sum[x][1]-sum[x][2]); } } cout<<dp[n][n][K]; return 0; }