思路:
因为m最大只有2,所以可以先算m==1的时候,就相当于求最大m子串和,状态转移方程为 :
dp[i][k][0]=max(dp[i-1][k][0],dp[i-1][1][k]);
dp[i][k][1]=max(dp[i-1][k][1],max(dp[i-1][k-1][1],dp[i-1][k-1][0]))+num[i];

然后m==2的时候,用dp[i][j][k]来表示,第一列为1-i,第二列为1-j,k为选的k个矩形。 sum[n][1]表示第一列的前缀和,sum[n][2]表示第二列的前缀和。
计算的时候,我们可以当做是分别计算第一列和第二列的最大m子串和,然后再把他们两列进行整合,因此可以分为四种情况:
计算第一列的时候:
dp[i][j][k]=max(dp[i][j][k],dp[t][j][k-1]+sum[i][1]-sum[t][1]);
计算第二列的时候:
dp[i][j][k]=max(dp[i][j][k],dp[i][t][k-1]+sum[j][2]-sum[t][2]);
当i==j的时候,会有他们两列的子串重合为一个矩形的可能:
dp[i][j][k]=max(dp[i][j][k],dp[t][t][k-1]+sum[i][1]-sum[t][1]+sum[j][2]-sum[t][2]);
什么都不选的情况:
dp[i][j][k]=max(dp[i-1][j][k],dp[i][j-1][k]);

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stack>
#include <queue>
#include <cmath>
#define ll long long
#define pi 3.1415927
#define inf 0x3f3f3f3f
#define mod 1000000007
using namespace std;
int sum[105][5],dp[105][105][12],num[105][5];
int main ()
{

    int T,n,m,i,t,j,k,p;
    cin>>n>>m>>k;
    for(i=1;i<=n;++i)
        for(j=1;j<=m;++j){
            cin>>num[i][j];
            sum[i][j]=sum[i-1][j]+num[i][j]; //计算前缀和
        }

    if(m==1)
    {
        for(i=1;i<=n;++i)
            for(int kk=1;kk<=k;++kk){//m==1的时候,相当于求最大m子串和
                dp[i][0][kk]=max(dp[i-1][0][kk],dp[i-1][1][kk]);
                dp[i][1][kk]=max(dp[i-1][1][kk],max(dp[i-1][1][kk-1],dp[i-1][0][kk-1]))+num[i][1];
            }
        p=max(dp[n][1][k],dp[n][0][k]);
        cout<<p<<endl;
    }
    else 
    {
        for(i=1;i<=n;++i)
            for(j=1;j<=n;++j)
                for(int kk=1;kk<=k;++kk)
                {
                    dp[i][j][kk]=max(dp[i-1][j][kk],dp[i][j-1][kk]); //什么都不选的情况
                    for(t=0;t<i;++t)
                        dp[i][j][kk]=max(dp[i][j][kk],dp[t][j][kk-1]+sum[i][1]-sum[t][1]); //在第一列选区间
                    for(t=0;t<j;++t)
                        dp[i][j][kk]=max(dp[i][j][kk],dp[i][t][kk-1]+sum[j][2]-sum[t][2]); //在第二列选区间
                    if(i==j)
                        for(t=0;t<j;++t) //当i==j的时候,有可能出现区间相同的情况
                            dp[i][j][kk]=max(dp[i][j][kk],dp[t][t][kk-1]+sum[i][1]-sum[t][1]+sum[j][2]-sum[t][2]);
                }
        cout<<dp[n][n][k]<<endl;
    }
    return 0;
}