现在的位置: 首页 > 综合 > 正文

最大子矩阵和【dp】

2018年01月08日 ⁄ 综合 ⁄ 共 982字 ⁄ 字号 评论关闭
描述

布欧可以把人变成巧克力吃了来增加他的能量,也有可能减少。

现在布欧变了n*m个巧克力,并把巧克力排成一个n*m的矩形,现在布欧想选择一个子矩形,把这个子矩形吃了来增加他的能量,可他不知道选哪个才能使他的能量增加值p最大,布欧也可以选择一个都不吃,这样p
= 0

现在布欧要你告诉他p的最大值,不然他就先把你变成巧克力吃了!

输入
第一行:一个整数T 代表测试个数,
接着T组测试数据。

对每组测试数据:
第一行:n m 两个整数
接着n行每行m个空格隔开的整数a(i,j)代表对应巧克力的能量值(注意可以是负数,吃了能量减少)

1<=n,m<=300
-1000<= a(i,j) <= 1000

输出
T行
每行一个整数 p
样例输入
3
3 3
1 -1 4
2 -2 3
3 -10 1
3 3
-1 -1 -1
-1 -1 -1
-1 -1 -1
3 3
1 1 -10
-1 1 -10
1 1 -10

样例输出 

 8 

 0 

 4

 解法:通过把矩阵的每行与下面的每一行压缩成一维数组,然后求最大连续子段和的问题

 思想在代码里,通过例子简单的模拟一下就懂

 AC code

#include<stdio.h>
#include<string.h>
int MaxSubstring(int *b,int n)/*求最大连续子段和*/
{
    int max;
	int i;
	int dp;
	max=0;
	dp=0;
	for(i=0;i<n;i++)
	{
		if(dp>=0)dp+=b[i];
		   else dp=b[i];
		if(dp>max)max=dp;
	}
	return max;
}
int main()
{
	int T;
	int i,j,k;
	int n,m;
	int a[310][310];
	int b[310];
	int sum,max;
	scanf("%d",&T);
	while(T--)
	{
	   scanf("%d%d",&n,&m);
	   memset(a,0,sizeof(a));
	   for(i=0;i<n;i++)
		   for(j=0;j<m;j++)
			   scanf("%d",&a[i][j]);
       max=0;
       for(i=0;i<n;i++)
	   {
	       for(k=0;k<m;k++)
			    b[k]=0;/*更新b数组*/
		   for(j=i;j<n;j++)
		   {
		      for(k=0;k<m;k++)
				   b[k]+=a[j][k];/*压缩处*/
			  sum=MaxSubstring(b,k);
			  if(sum>max)max=sum;
		   }
	   }
	   printf("%d\n",max);
	}
    return 0;
}

抱歉!评论已关闭.