动态规划 BZOJ1084 [SCOI2005]最大子矩阵

1084: [SCOI2005]最大子矩阵

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2771  Solved: 1379
[Submit][Status][Discuss]

Description

  这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵
不能相互重叠。

Input

  第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的
分值的绝对值不超过32767)。

Output

  只有一行为k个子矩阵分值之和最大为多少。

Sample Input

3 2 2
1 -3
2 3
-2 3

Sample Output

9

HINT

 

Source

通读题目有时很重要,比如这个题……

发现可以根据m=1和m=2分类讨论地写,用前缀和容易想到,代码通俗易懂

 1 #include<iostream>
 2 #include<cstdio> 
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int n,m,k,a;
 7 int sum[110][3],f[110][12],g[110][110][12];
 8 int main(){
 9     scanf("%d%d%d",&n,&m,&k);
10     for(int i=1;i<=n;i++)
11         for(int j=1;j<=m;j++){
12             scanf("%d",&a);
13             sum[i][j]=sum[i-1][j]+a;    
14         }
15     if(m==1){
16         for(int i=1;i<=n;i++)
17             for(int j=1;j<=k;j++){
18                 f[i][j]=f[i-1][j];
19                 for(int p=0;p<=i-1;p++) f[i][j]=max(f[i][j],f[p][j-1]+sum[i][1]-sum[p][1]);
20             }
21         printf("%d
",f[n][k]);
22     }
23     else{
24         for(int i=1;i<=n;i++)
25             for(int j=1;j<=n;j++)
26                 for(int t=1;t<=k;t++){
27                     g[i][j][t]=max(g[i-1][j][t],g[i][j-1][t]);
28                     for(int p=0;p<=i-1;p++) g[i][j][t]=max(g[i][j][t],g[p][j][t-1]+sum[i][1]-sum[p][1]);
29                     for(int p=0;p<=j-1;p++) g[i][j][t]=max(g[i][j][t],g[i][p][t-1]+sum[j][2]-sum[p][2]);
30                     if(i==j)
31                         for(int p=0;p<=i-1;p++) g[i][j][t]=max(g[i][j][t],g[p][p][t-1]+sum[i][1]-sum[p][1]+sum[i][2]-sum[p][2]); 
32                 }
33         printf("%d
",g[n][n][k]);
34     }
35     return 0;
36 }
原文地址:https://www.cnblogs.com/zwube/p/7077461.html