Poj 1050 dp

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;
}

猜你喜欢

转载自blog.csdn.net/m0_38062488/article/details/80634830