1. 程式人生 > >BZOJ(6) 1084: [SCOI2005]最大子矩陣

BZOJ(6) 1084: [SCOI2005]最大子矩陣

else cout ack stat can end com sin source

1084: [SCOI2005]最大子矩陣

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 3566 Solved: 1785
[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分開處理。

當m=1時,有:f[i][k]表示到前i個數為止,選k的子矩陣的最優解。

那麽第i個數有選和不選兩種情況

  不選:f[i][k]=max(f[i][k],f[i-1][k]);

  選:f[i][k]=max(f[i][k],f[q][k-1]+sum[i][1]-sum[q][1])

當m=2時,有:g[k][i][j]表示左列到前i個,右列到前j個數為止,選出k個子矩陣的最優解。

可先分開考慮,對於每一列有選和不選兩種情況。

然後當i==j時,考慮兩列同時選和不選兩種情況。

  有:

g[j][i1][i2]=max(g[j][i1-1][i2],g[j][i1][i2]);

g[j][i1][i2]=max(g[j][i1][i2-1],g[j][i1][i2]);

g[j][i1][i2]=max(g[j-1][q][i2]+sum[i1][1]-sum[q][1],g[j][i1][i2]);

g[j][i1][i2]=max(g[j-1][i1][q]+sum[i2][2]-sum[q][2],g[j][i1][i2]);
g[j][i1][i2]=max(g[j-1][q][q]+sum[i1][1]-sum[q][1]+sum[i2][2]-sum[q][2],g[j][i1][i2]);

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,k;
int sum[103][3];
int a[103][3],f[103][103],g[103][103][103];
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]);
            sum[i][j]=sum[i-1][j]+a[i][j];
        }
    /*for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cout<<sum[i][j]<<" ";
        }
        cout<<endl;
    }*/
    if(m==1){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=k;j++){
                f[i][j]=max(f[i-1][j],f[i][j]);
                for(int q=0;q<i;q++)
                    f[i][j]=max(f[i][j],f[q][j-1]+sum[i][1]-sum[q][1]);
            }
        }
        cout<<f[n][k];
    }
    else if(m==2){
        for(int i1=1;i1<=n;i1++)
            for(int i2=1;i2<=n;i2++)
                for(int j=1;j<=k;j++){
                    g[j][i1][i2]=max(g[j][i1-1][i2],g[j][i1][i2]);
                    g[j][i1][i2]=max(g[j][i1][i2-1],g[j][i1][i2]);
                    for(int q=0;q<i1;q++)
                        g[j][i1][i2]=max(g[j-1][q][i2]+sum[i1][1]-sum[q][1],g[j][i1][i2]);
                    for(int q=0;q<i2;q++)
                        g[j][i1][i2]=max(g[j-1][i1][q]+sum[i2][2]-sum[q][2],g[j][i1][i2]);
                    if(i1==i2)
                        for(int q=0;q<i1;q++)
                            g[j][i1][i2]=max(g[j-1][q][q]+sum[i1][1]-sum[q][1]+sum[i2][2]-sum[q][2],g[j][i1][i2]);
                //    cout<<g[j][i1][i2]<<"-->";
                }
        cout<<g[k][n][n];
    }
}
/*
3 2 2
1 -3
2 3
-2 3
*/

BZOJ(6) 1084: [SCOI2005]最大子矩陣