【BZOJ 1084】 [SCOI2005]最大子矩阵

来源:互联网 发布:linux编程实践教程 编辑:程序博客网 时间:2024/05/13 11:36

1084: [SCOI2005]最大子矩阵

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1325  Solved: 670
[Submit][Status]

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


dp。


注意到m=1/2,所以两种情况分别算。


m=1时:

f[i][j]表示前i数选出j个子矩阵,sum[i]为前缀和。


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



m=2时:

w[i][j][k]表示左边一列的前i行,右边一列的前j行,分成k个子矩阵。


有三种转移方法:

1.从左边选择一列w[i][j][k]=max(w[i][j][k],w[p][j][k-1]+sum[i][1]-sum[p][1])


2.从右边选择一列w[i][j][k]=max(w[i][j][k],w[i][p][k-1]+sum[j][2]-sum[p][2])


3.如果i=j还可以选择宽为2的矩阵

w[i][j][k]=max(w[i][j][k],w[p][p][k-1]+sum[i][1]-sum[p][1]+sum[i][2]-sum[p][2])


这样就能把所有状态都表示出来了。


#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cstdlib>#define inf 0x3f3f3f3fusing namespace std;int a[105][3],sum[105][3],f[105][105],w[105][105][15],n,m,k;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",&a[i][j]);if (!k){cout<<0<<endl;return 0;}if (m==1){sum[0][1]=0;for (int i=1;i<=n;i++)sum[i][1]=sum[i-1][1]+a[i][1];for (int i=0;i<=n;i++)for (int j=1;j<=k;j++)f[i][j]=-inf;for (int i=1;i<=n;i++)for (int j=1;j<=min(i,k);j++){f[i][j]=f[i-1][j];for (int p=0;p<i;p++)f[i][j]=max(f[i][j],f[p][j-1]+sum[i][1]-sum[p][1]);}cout<<f[n][k]<<endl;}else{sum[0][1]=sum[0][2]=0;for (int i=1;i<=n;i++)for (int j=1;j<=2;j++)sum[i][j]=sum[i-1][j]+a[i][j];for (int i=0;i<=n;i++)for (int j=0;j<=n;j++)for (int t=1;t<=k;t++)w[i][j][t]=-inf;for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)for (int t=1;t<=min(k,i+j);t++){w[i][j][t]=max(w[i][j-1][t],w[i-1][j][t]);for (int p=0;p<i;p++)w[i][j][t]=max(w[i][j][t],w[p][j][t-1]+sum[i][1]-sum[p][1]);for (int p=0;p<j;p++)w[i][j][t]=max(w[i][j][t],w[i][p][t-1]+sum[j][2]-sum[p][2]);if (i==j){for (int p=0;p<i;p++)w[i][j][t]=max(w[i][j][t],w[p][p][t-1]+sum[i][1]-sum[p][1]+sum[i][2]-sum[p][2]);}}cout<<w[n][n][k]<<endl;}return 0;}


感悟:

这道题的关键在于发现m的特殊之处,然后就可以暴力的来做了

1 0
原创粉丝点击