码迷,mamicode.com
首页 > 其他好文 > 详细

[Luogu 2331] [SCOI2005]最大子矩阵

时间:2017-10-12 10:10:32      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:sans   family   pen   gif   bsp   turn   opened   strong   输入输出   

[Luogu 2331] [SCOI2005]最大子矩阵

题目描述

这里有一个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题,由于看题太过迅速,竟然没有看清m<=2!!!(好气哦qaq)

题解:

既然在知道了m<=2的条件下,那么应该是可以想到,对m=1和m=2分别考虑

(1)m=1的情况其实就是一个求k个最大字段和

那么可以用一个二维数组f[i][j]表示到了第i位选取了j个字段

那么转移就是分为不选第i位和选第i位的情况

f[i][j]=f[i-1][j]

f[i][j]=max(f[i][j],f[l-1][j-1]+sum[i]-sum[l])(1<=l<=i)

(2)m=2的情况就是一个三维DP

f[i][j][k]表示第一列选到第i行,第二列选到第j行,一共选了k个矩形

那么转移分为四种第i和第j行都不选,选第i行,选第j行,同时选第i和第j行(前提i=j)

那么具体的转移方程请见程序

技术分享
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=110;
 4 int n,m,k,sum,ans;
 5 int a[N][3],sum1[N],sum2[N],f[N][N][12],g[N][12];
 6 int main(){
 7     scanf("%d%d%d",&n,&m,&k);
 8     for (int i=1;i<=n;++i)
 9         for (int j=1;j<=m;++j) 
10             scanf("%d",&a[i][j]);
11     for (int i=1;i<=n;++i) sum1[i]=sum1[i-1]+a[i][1];
12     if (m==2) for (int i=1;i<=n;++i) sum2[i]=sum2[i-1]+a[i][2];
13     if (m==1){
14         for (int i=1;i<=k;++i) g[0][i]=0;
15         for (int i=1;i<=n;++i)
16             for (int j=1;j<=k;++j){
17                 g[i][j]=g[i-1][j];
18                 for (int l=1;l<=i;++l) g[i][j]=max(g[i][j],g[l-1][j-1]+sum1[i]-sum1[l-1]);
19             }
20         printf("%d",g[n][k]); return 0;
21     }
22     for (int i=0;i<=k;++i) f[0][0][i]=0;
23     for (int i=1;i<=n;++i)
24         for (int j=1;j<=n;++j)
25             for (int l=1;l<=k;++l){
26                 f[i][j][l]=max(f[i-1][j][l],f[i][j-1][l]);
27                 for (int h=1;h<=i;++h)
28                     f[i][j][l]=max(f[i][j][l],f[h-1][j][l-1]+sum1[i]-sum1[h-1]);
29                 for (int h=1;h<=j;++h)
30                     f[i][j][l]=max(f[i][j][l],f[i][h-1][l-1]+sum2[j]-sum2[h-1]);
31                 if (i==j) for (int h=1;h<=i;++h) f[i][j][l]=max(f[i][j][l],f[h-1][h-1][l-1]+sum1[i]+sum2[j]-sum1[h-1]-sum2[h-1]);
32             }
33     printf("%d",f[n][n][k]);    
34 }
View Code

 

[Luogu 2331] [SCOI2005]最大子矩阵

标签:sans   family   pen   gif   bsp   turn   opened   strong   输入输出   

原文地址:http://www.cnblogs.com/logic-yzf/p/7654383.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!