Description
这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵不能相互重叠。
第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767)。
Output
只有一行为k个子矩阵分值之和最大为多少。
题解
又题意可知,m非常小(<=2 !!!),所以分类讨论的DP ① m=1 设f[i][k]表示前i个数取了k个矩阵的最优解 1、选,f[i][k] = max{f[pos][k-1]+sum[i][1]-sum[pos][1]} 2、不选,f[i][k] = max{f[i-1][k],f[i][k]} ② m=1 设w[i][j][k]:第一行取i个,第二行取j个,以取了k个矩阵的最优解 1、什么都不干 w[i][j][k] = max{w[i-1][j][k],w[i][j-1][k]} 2、只从第一段中取 w[i][j][k] = max{w[pos][j][k-1]+sum[i][1]-sum[pos][1]} 3、只从第二段中取 w[i][j][k] = max{w[i][pos][k-1]+sum[j][2]-sum[pos][2]} 4、当i==j时,可以两列一起取 w[i][j][k] = max{w[pos][pos][k-1]+sum[i][1]+sum[j][1]-sum[pos][1]-sum[pos][2]}
取所有的max就可以啦
代码
using namespace std;
int a,f[N][
15],w[N][N][
15],sum[N][
3];
int n,
m,K;
int main()
{
scanf(
"%d%d%d",&n,&
m,&K);
memset(sum,
0,sizeof(sum));
rep(i,
1,n)
rep(j,
1,
m)
{
scanf(
"%d",&a);
sum[i][j] = sum[i-
1][j] + a;
}
if(
m ==
1)
{
rep(i,
0,n) rep(k,
1,K) f[i][k] = -inf;
rep(i,
1,n)
rep(k,
1,K)
{
f[i][k] = f[i-
1][k];
for(
int pos =
0;
pos < i;
pos++)
f[i][k] = max(f[i][k],f[
pos][k-
1]+sum[i][
1]-sum[
pos][
1]);
}
printf(
"%d\n",f[n][K]);
}
else
{
rep(i,
0,n) rep(j,
0,n) rep(k,
1,K) w[i][j][k] = -inf;
rep(i,
1,n) rep(j,
1,n) rep(k,
1,K)
{
w[i][j][k] = max(w[i-
1][j][k],w[i][j-
1][k]);
rep(
pos,
0,i-
1)
w[i][j][k] = max(w[i][j][k],w[
pos][j][k-
1]+sum[i][
1]-sum[
pos][
1]);
rep(
pos,
0,j-
1)
w[i][j][k] = max(w[i][j][k],w[i][
pos][k-
1]+sum[j][
2]-sum[
pos][
2]);
if(i == j)
rep(
pos,
0,i-
1)
w[i][j][k] = max(w[i][j][k],w[
pos][
pos][k-
1]+sum[i][
1]-sum[
pos][
1]+sum[j][
2]-sum[
pos][
2]);
}
printf(
"%d\n",w[n][n][K]);
}
return 0;
}
转载请注明原文地址: https://ju.6miu.com/read-17355.html