首页 > 技术文章 > Task 4.5 求二维数组中的最大连通子数组之和

mengxiangjialzh 2015-06-12 00:10 原文

 任务:输入一个二维整形数组,数组里有正数也有负数。 求所有子数组的和的最大值。要求时间复杂度为O(n)。

1.设计思想:因为用之前的解决子数组最大和的问题的思路一直没能解决这个问题,后来看到同学使用将矩阵转化为图的思路将结果得出了,所以我就沿着这个思路一步一步的分析了一下。开始先将将二维矩阵转换成图的存储形式,当两个相邻的数之间是联通的时,记长度为1,否则就是0;将整个图从每个点都开始遍历一遍,遍历过程中时,当和小于0时断开两点间的路,当和大于最大和时改变最大和的值,取以每个点为起点遍历的和的最大值即时最大联通子数组的和。遍历时,选取已遍历的联通子数组周围最大值遍历。经过重复的几次遍历就可以确定此数组中最大连通数组和了。

2.源代码:

#include<iostream>
#define N 100
#include<ctime>
using namespace std;

typedef struct
{
    int d[N];
    int a[N][N];
    int x;
}A;

void set(A &shu, int x, int y)//x,y分别是行数和列数
{
    shu.x = x*y;
    srand((unsigned)time(NULL));
    for (int i = 1; i <= shu.x; i++)
    {
        shu.d[i] = rand() % 10;
        if (rand() % 2 == 1)
            shu.d[i] = shu.d[i] * (-1);
    }//随机生成数组的数
    for (int i = 1; i <= shu.x; i += y)
    {
        for (int j = i; j <= i + y - 2; j++)
        {
            shu.a[j][j + 1] = 1;
            shu.a[j + 1][j] = 1;
        }
    }
    for (int i = 1 + y; i<shu.x; i += y)
    {
        for (int j = i; j <= i + x - 1; j++)
        {
            shu.a[j][j - y] = 1;
            shu.a[j - y][j] = 1;
        }
    }//将随机生成的一维数组转换成二维的图的形式
}
void output(A shu)
{
    for (int i = 1; i <= shu.x; i++)
    {
        cout  << shu.d[i] ;
        if (shu.a[i][i + 1] == 1)
            cout << "   ";
        else
            cout << endl;
    }
}
void bianli(A &shu, int v, int visit[], int &b, int &max, int x)
{
    visit[v] = 1;

    max += shu.d[v];
    if (max >= b)
        b = max;

    int a = 0, bo = 0;
    for (int w = 1; w <= shu.x; w++)
    {
        for (int c = 1; c <= shu.x; c++)
        {
            if ((visit[w] == 0) && (shu.a[c][w] == 1) && (visit[c] == 1))
            {
                a = w; bo = 1; break;
            }
        }
        if (bo == 1)
            break;
    }
    for (int w = 1; w <= shu.x; w++)
    {
        for (int c = 1; c <= shu.x; c++)
        {
            if ((visit[w] == 0) && (shu.a[c][w] == 1) && (visit[c] == 1))
            {
                if (shu.d[a]<shu.d[w])
                    a = w;
                
            }
        }
    }
    if (b + shu.d[a]<0)
    {
        shu.a[v][a] = 0;
    }
    else
        bianli(shu, a, visit, b, max, x);
}
//遍历

int NoVisit(int visit[], A shu)
{
    int k = 0, i;
    for (i = 1; i <= shu.x; i++)
    {
        if (visit[i] == 0)
        {
            k = i;
            break;
        }
    }
    return k;
}//判断图中没有visit的项

int main()
{
    cout << "请输入数组行数和列数:" << endl;
    int x, y;
    cin >> x >> y;
    A shu;
    set(shu, x, y);
    output(shu);

    int v = 1, b[N] = { 0 }, h = 0;
    
    for (int i = 1; i <= shu.x; i++)
    {
        if (shu.d[i]<0)
        {
            b[i] = shu.d[i];
        }
        else
        {
            int visit[N] = { 0 };
            int max = 0;
            bianli(shu, i, visit, b[i], max, x);
        }
    }

    int max = b[1];
    for (int i = 2; i <= shu.x; i++)
    {
        if (b[i]>max)
            max = b[i];
    }
    cout << "最大联通子数组的和为:" << max << endl;
}

 

推荐阅读