[SCOI2005]最大子矩阵(线性dp)

▼魔方 西西 提交于 2019-11-27 14:04:36

最大子矩阵

题目描述

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

输入格式

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

输出格式

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

输入输出样例

输入 
3 2 2
1 -3
2 3
-2 3
输出 
9题目思路注意到m只会为1或2,为1时就是简单的一维线性dp过去,为2时就多加几个决策,有点麻烦dp1[i][j]表示在所取矩形最大坐标为i且取k个矩形的最大值,dp2[i][j][t]表示在所取矩形第一位最大坐标为i第二维最大坐标为j且取k个矩形的最大值
#include<bits/stdc++.h>
#define mod 9999973
#define ll long long
using namespace std;
int n,m,k,dp2[101][101][11],g[101][3],dp1[101][11],sum1[101],sum2[101];
int main()
{
    memset(dp1,128,sizeof(dp1));
    memset(dp2,128,sizeof(dp2));
    cin>>n>>m>>k;
    for(int i = 1;i<=n;i++)
        for(int j = 1;j<=m;j++)
            cin>>g[i][j];
    if(m==1)
    {
        for(int i = 1;i<=n;i++)
            sum1[i] = sum1[i-1]+g[i][1];
        dp1[0][0] = 0;
        for(int i = 1;i<=n;i++)
        {
            dp1[i][0] = 0;
            for(int j = 0;j<i;j++)
                for(int t = 1;t<=k;t++)
                    dp1[i][t] = max(max(dp1[i-1][t],dp1[i][t]),dp1[j][t-1]+sum1[i]-sum1[j]);
        }
        cout<<dp1[n][k];
    }
    else
    {
        for(int i = 1;i<=n;i++)
            sum1[i] = sum1[i-1]+g[i][1];
        for(int i = 1;i<=n;i++)
            sum2[i] = sum2[i-1]+g[i][2];
        dp2[0][0][0] = 0;
        for(int i = 1;i<=n;i++)
        {
            dp2[i][i][0] = 0;
            for(int j = 0;j<=i;j++)
            {
                for(int t = 0;t<=i;t++)
                {
                    for(int h = 1;h<=k;h++)
                    {
                        int p = max(j,t);    
                        if(t)
                            dp2[i][t][h] = max(max(dp2[i][t][h],max(dp2[i-1][t-1][h],max(dp2[i-1][t][h],dp2[i][t-1][h]))),dp2[j][t][h-1]+sum1[i]-sum1[j]);
                        else
                            dp2[i][t][h] = max(max(dp2[i][t][h],max(dp2[i-1][t][h],max(dp2[i-1][t][h],dp2[i][t][h]))),dp2[j][t][h-1]+sum1[i]-sum1[j]);
                        if(j)
                            dp2[j][i][h] = max(max(dp2[j][i][h],max(dp2[j-1][i-1][h],max(dp2[j-1][i][h],dp2[j][i-1][h]))),dp2[j][t][h-1]+sum2[i]-sum2[t]);
                        else
                            dp2[j][i][h] = max(max(dp2[j][i][h],max(dp2[j][i-1][h],max(dp2[j][i][h],dp2[j][i-1][h]))),dp2[j][t][h-1]+sum2[i]-sum2[t]);
                        dp2[i][i][h] = max(max(dp2[i][i][h],max(dp2[i-1][i-1][h],max(dp2[i-1][i][h],dp2[i][i-1][h]))),dp2[j][t][h-1]+sum1[i]-sum1[p]+sum2[i]-sum2[p]);
                    }
                }
            }
        }
        int ans = 0;
        for(int i = 0;i<=n;i++)
            for(int j = 0;j<=n;j++)
             ans = max(ans,dp2[i][j][k]);
        cout<<ans;
    }  
    return 0;
}

 

 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!