Poj 1050
问题分析
这是一个最大子矩阵和问题,已知最大子段和的求解方法,可以通过降维来实现。
降维即把第i行至第j行同列相加,变为一维的最大子段和问题,然后整个问题可转化为,求:
1-1,1-2,1-3,…1-n;
2-2,2-3,2-4,…2-n;
3-3,3-4,3-5,…3-n;
…….
n-n;
各个降维后的各个记录的最大子段和的最大值
最大子段和问题:
满足最优子结构,还要满足无后效性,则只能用当前数据和先前产生的数据来求子段,所以就有以第i个数据结尾来区分不同子段,并可以使后继数据可以使用前一数据;
dp[i-1]>0; 则 dp[i]=data[i]+dp[i-1];
dp[i-1]<=0; 则 dp[i]=data[i];
代码部分
#include <stdio.h>
#include <stdlib.h>
#define NMAX 101
int S[NMAX][NMAX];//元数据
int K[NMAX];//降维后的记录
int getone(int n)//每条记录的最大子段和
{
int max=0,sum=0;
for(int i=1;i<=n;i++)
{
if(sum>0)
{
sum+=K[i];
}
else
{
sum=K[i];
}
if(sum>max)
{
max=sum;
}
}
return max;
}
void buildK(int n,int i,int j)//降维过程
{
for(int k=1;k<=n;k++)
{
K[k]=0;
}
for(int k=1;k<=n;k++)
{
for(int l=i;l<=j;l++)
{
K[k]+=S[l][k];
}
}
}
int GetS(void)//接收数据
{
int n=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&S[i][j]);
}
}
return n;
}
int Getanswer(int n)//得到结果
{
int answer=0;
int tmp=0;
for(int beg=1;beg<=n;beg++)
{
for(int endd=beg;endd<=n;endd++)
{
tmp=0;
buildK(n,beg,endd);
tmp=getone(n);
if(tmp>answer)
{
answer=tmp;//更新
}
}
}
return answer;
}
void showone(void)//测试一组
{
int n=0;
n=GetS();
printf("%d\n",Getanswer(n));
}
int main()
{
showone();
return 0;
}