[dp]洛谷 P2331 最大子矩阵

题目描述

这里有一个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
输出样例#1:
9

题解

  • dp[i][j][p]表示扫描到第一列i位置与第二列j位置且选取p个矩阵时的答案

  • 三种转移:第一列取一段,第列取一段,取一个宽度为2的矩阵

代码

#include<iostream>
#include<cstdio>
using namespace std;
const int mxn=105;
int n,m,k,dp[mxn][mxn][12],map[mxn][3],qz[mxn][3],two[mxn];
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) scanf("%d",&map[i][j]);
    for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) qz[i][j]=qz[i-1][j]+map[i][j];
    for (int i=1;i<=n;i++) two[i]=two[i-1]+map[i][1]+map[i][2];
    for (int i=1;i<=n;i++)
    	for (int j=1;j<=n;j++)
	    	for(int p=k;p>=1;p--)
	        {
	        	dp[i][j][p]=max(dp[i][j-1][p],dp[i-1][j][p]);
	            for (int z=1;z<=i;z++) dp[i][j][p]=max(dp[i][j][p],dp[z-1][j][p-1]+qz[i][1]-qz[z-1][1]);
	            for (int z=1;z<=j;z++) dp[i][j][p]=max(dp[i][j][p],dp[i][z-1][p-1]+qz[j][2]-qz[z-1][2]);
	            for (int z=1;z<=min(i,j);z++) dp[i][j][p]=max(dp[i][j][p],dp[z-1][z-1][p-1]+two[min(i,j)]-two[z-1]);
	        }
    printf("%d\n",dp[n][n][k]);
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/9205815.html