题目是说有一家公司要挖金矿,但是资金有限,因此要合理选择一块矩形的矿地,金矿可以分割成1*1的小格,给出金矿的大小n*m,以及限制金额S。接下来是两个n*m的矩阵,第一个表示花费的金额,第二个表示收益。要求输出最大收益(注:选择的区域必须是矩形)
其实这个就跟dp里的最大子矩阵问题差不多,不过这里面没有负数,却多了一个花费金额来限制。
首先将每一行都压缩,也就是将前几项都加起来存到当前数组中,这样可以避免在后面重复计算前几项的和,而要单独用第i行第j项时,只需a[i][j]-=a[i][j-1]
for
(i=1;i<=n;i++)
{
for
(j=1;j<=m;j++)
{
if
(j!=1)
{
a[i][j]+=a[i][j-1];
b[i][j]+=b[i][j-1];
}
}
}
#include<stdio.h>
#include<string.h>
int
a[210][210],b[210][210],c[210][210];
int
main()
{
int
T,n,m,i,j,t,k,xx,x,y,l;
scanf
(
"%d"
,&T);
while
(T--)
{
memset
(a,0,
sizeof
(a));
memset
(b,0,
sizeof
(b));
memset
(c,0,
sizeof
(c));
scanf
(
"%d%d%d"
,&n,&m,&l);
for
(i=1;i<=n;i++)
{
for
(j=1;j<=m;j++)
{
scanf
(
"%d"
,&a[i][j]);
}
}
for
(i=1;i<=n;i++)
{
for
(j=1;j<=m;j++)
{
scanf
(
"%d"
,&b[i][j]);
}
}
for
(i=1;i<=n;i++)//压缩行
{
for
(j=1;j<=m;j++)
{
if
(j!=1)
{
a[i][j]+=a[i][j-1];
b[i][j]+=b[i][j-1];
}
}
}
for
(k=1;k<=m;k++)//从第k列开始
{
for
(i=k;i<=m;i++)//从k往后的每一列
{
t=1;x=0;y=0;
for
(j=1;j<=n;j++)//对第i列每一行进行规划
{
x+=(a[j][i]-a[j][k-1]); //计算花费
if
(x>l)//花费超出,则减去最上面的,直到不超
{
if
(y>c[j-1][i])
c[j-1][i]=y;
while
(x>l)
{
x-=(a[t][i]-a[t][k-1]);
y-=(b[t][i]-b[t][k-1]);
t++;
}
y+=(b[j][i]-b[j][k-1]);//计算收益
}
else
y+=(b[j][i]-b[j][k-1]);
//否则,继续
}
if
(y>c[j-1][i])//到最下面,若收益比之前的多,则记录
c[j-1][i]=y;
}
}
xx=0;//找到最大收益
for
(i=1;i<=n;i++)
{
for
(j=1;j<=m;j++)
{
if
(c[i][j]>xx)
xx=c[i][j];
}
}
printf
(
"%d\n"
,xx);
}
return
0;
}
Coyouth 1583 问题 G: Enclosure Plan 解题报告,布布扣,bubuko.com
Coyouth 1583 问题 G: Enclosure Plan 解题报告
原文:http://www.cnblogs.com/qianshihuimou/p/3594877.html