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
1 -3
2 3
-2 3
Sample Output
9
题解
应该算区间dp的一种吧,因为m<=2,所以分两类来考虑。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
int n,m,K;
int s1[102],s2[102],f[102][12],F[102][102][12];
void init1()
{
int i,x;
for(i=1;i<=n;i++)
{scanf("%d",&x);
s1[i]=s1[i-1]+x;
}
}
void doit1()
{
int i,j,k,w;
for(i=1;i<=n;i++)
for(j=0;j<i;j++)
{w=min(K,i);
for(k=1;k<=w;k++)
{if(j>=k-1)
{f[i][k]=max(f[i][k],f[j][k-1]+s1[i]-s1[j]);
f[i][k]=max(f[i][k],f[j][k]);
}
}
}
printf("%d\n",f[n][K]);
/*for(i=1;i<=n;i++)
{for(j=0;j<=K;j++)
printf("%d ",f[i][j]);
printf("\n");
}*/
}
void init2()
{
int i,x,y;
for(i=1;i<=n;i++)
{scanf("%d%d",&x,&y);
s1[i]=s1[i-1]+x;
s2[i]=s2[i-1]+y;
}
}
void doit2()
{
int i,j,k,l,w;
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
{if(i==j)
{w=min(i,K);
for(k=0;k<i;k++)
for(l=1;l<=w;l++)
{if(k>=l-1)
{F[i][i][l]=max(F[i][i][l],F[k][k][l-1]+s1[i]-s1[k]+s2[i]-s2[k]);
F[i][i][l]=max(F[i][i][l],F[k][k][l]);
}
}
}
w=min(i,K);
for(k=0;k<i;k++)
for(l=1;l<=w;l++)
{if(k>=l-1)
{F[i][j][l]=max(F[i][j][l],F[k][j][l-1]+s1[i]-s1[k]);
F[i][j][l]=max(F[i][j][l],F[k][j][l]);
}
}
w=min(j,K);
for(k=0;k<j;k++)
for(l=1;l<=w;l++)
{if(k>=l-1)
{F[i][j][l]=max(F[i][j][l],F[i][k][l-1]+s2[j]-s2[k]);
F[i][j][l]=max(F[i][j][l],F[i][k][l]);
}
}
}
printf("%d\n",F[n][n][K]);
/*for(i=1;i<=n;i++)
{for(j=0;j<=K;j++)
printf("%d ",f[i][j]);
printf("\n");
}*/
}
int main()
{
scanf("%d%d%d",&n,&m,&K);
if(m==1)
{init1(); doit1();}
else
{init2(); doit2();}
return 0;
}