保研机试刷题——2018年南大机试第一题,最大子矩阵和

题目是这样的:

已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵。
比如,如下4 * 4的矩阵

0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2

的最大子矩阵是

9 2
-4 1
-1 8

这个子矩阵的大小是15。

输入

输入是一个N * N的矩阵。输入的第一行给出N (0 < N <= 100)。
再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给出第二行的N个整数……)给出矩阵中的N2个整数,整数之间由空白字符分隔(空格或者空行)。
已知矩阵中整数的范围都在[-127, 127]。

输出

测试数据可能有多组,对于每组测试数据,输出最大子矩阵的大小。

样例输入

1
27 
3
-40 29 -16 
38 18 22 
24 -35 5 

样例输出

27
78

其实吧,这题不难,主要就是要能转过来一个弯:

将二维数组转化为一维数组,然后通过该一维数组来找到最大连续子序列。

比如最大的连续子矩阵的和为从第 i 行 到 第 j 行的元素在列的方向上相加,得到一个一维数组arrtemp[],然后计算出这个一维数组的最大子序列的和maxtemp,通过对 i 和 j 进行枚举(1<=i<=N, i<=j<=N),计算出N(N-1)/2 个 maxtemp,取其中最大的那个作为最终的最大子矩阵的值。

 

/*
    实际上就是最大连续子序列和的问题,只不过要对从i行到j行的所有的可能都枚举
    然后要设置一个Max值来进行保存并更新当前的最大值
*/
#include
#include
using namespace std;

int N;
int a[505][505];
int temp[505];

int max_oneVec(int an[])            //一维数组的动态规划
{
    int dp2[505];
    dp2[1]=an[1];                   //边界条件,第1个结尾的子串只能是自己
    int maxnum=dp2[1];              //标记最大值
    for(int i=2;i<=N;i++)           //从第2个开始
    {
        if(dp2[i-1]>0)
        {
            dp2[i] = dp2[i-1]+an[i];
        }else
        {
            dp2[i] = an[i];
        }
        if(dp2[i]>maxnum)
        {
            maxnum = dp2[i];        //更新最大值
        }
    }
    return maxnum;
}

int main()
{
    cin>>N;
    for(int i=1;i<=N;i++)
    {
        for(int j=1;j<=N;j++)
        {
            cin>>a[i][j];
        }
    }
    int maxres=0;
    for(int i=1;i<=N;i++)   //从第一行开始搜索
    {
        memset(temp,0,sizeof(temp));        //重置当前的dp数组
        for(int j=i;j<=N;j++)
        {
            for(int k=1;k<=N;k++)           //累加当前的从第i行到j行的数组值放入一维数组中
            {
                temp[k] += a[j][k];
            }
        }
        int maxtemp = max_oneVec(temp);     //该一维数组的最大值即为当前从i行到j行矩阵的最大值

        if(maxtemp>maxres)
        {
            maxres = maxtemp;
        }
    }
    cout<

 

你可能感兴趣的:(机试刷题,动态规划)