luoguP1115 最大子段和
从头到尾遍历数组,用sum记录遍历过来的和,过程中每当sum加上一个元素就尝试更新ans,并且若在过程中sum的值小于0了,就将sum的值置为0(意味着前面的元素都不要了,从下一个元素再开始累加),最后ans的结果就是最终答案。
下面是代码:
#include<iostream>
using namespace std;
int main()
{
int n;
int sum=0;
int ans=-0x3f3f3f3f;
int a;
cin>>n;
for(int i=1;i<=n;++i)
{
cin>>a;
sum+=a;
if(ans<sum) ans=sum;
if(sum<0) sum=0;
}
cout<<ans<<endl;
return 0;
}
luoguP1719 最大加权矩形
运用到了矩阵压缩,将二维的矩阵压缩成一维从而来维护子矩阵和等,例如有一个2x3的矩阵,我们想要找它的最大子矩阵和,我们只需要将两行同列的元素相加得到一个一维数组,然后再利用上面最大子段和的方法寻找即可,因为这样做最后压缩成的数组一个元素就顶以前矩阵2个元素的和,比如说压缩后数组的前两项的和就相当于原矩阵对应位置4个元素的和,所以这样做可以保证结果的正确性。
下面只需要遍历所有情况就好了,利用上面找最长字段和的方法时间上就是找到了列意义上的最大子矩阵和,那么我们只需要遍历所有行意义上的情况就行了,也就是说找出所有的行的组合方式。
下面是代码:
#include<iostream>
using namespace std;
int g[150][150];
int mi[150];
int main()
{
int n;
int sum=0;
int ans=-0x3f3f3f3f;
int max=-0x3f3f3f3f;
cin>>n;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
cin>>g[i][j];
}
}
for(int i=1;i<=n;++i)//遍历行
{
sum=0;
for(int k=1;k<=n;++k)//先对第i行单行找最大子矩阵和
{
sum+=g[i][k];
if(ans<sum) ans=sum;
if(sum<0) sum=0;
}
for(int k=1;k<=n;++k)//初始化mi数组为下面的操作做准备
{
mi[k]=g[i][k];
}
for(int j=i+1;j<=n;++j)//遍历剩下的行(为了找所有行的组合方法),每遍历到一行,就把这行加到mi数组中再找最大子矩阵和
{
for(int k=1;k<=n;++k)
{
mi[k]+=g[j][k];
}
sum=0;
for(int k=1;k<=n;++k)
{
sum+=mi[k];
if(ans<sum) ans=sum;
if(sum<0) sum=0;
}
}
}
cout<<ans<<endl;
return 0;
}