您的位置:首页 > 其它

最大子段和问题(nyoj 44 && 104)

2014-05-02 12:17 246 查看
nyoj44:点击打开链接

给一串数字,求连续非空子串的最大和。

int b = 0, sum = -10000000;
for(i = 0; i < n; i++)
{
if(b > 0)
b += a[i];
else
b = a[i];
if(sum < b)
sum = b;
}


nyoj104:点击打开链接

一个是一维的,一个是多维的,那么就把多维转化为一维的。

下面一段来自:这里

假设最大子矩阵的结果为从第r行到k行、从第i列到j列的子矩阵,如下所示(ari表示a[r][i],假设数组下标从1开始):

| a11 …… a1i ……a1j ……a1n |

| a21 …… a2i ……a2j ……a2n |

| . . . . . . . |

| . . . . . . . |

| ar1 …… ari ……arj ……arn |

| . . . . . . . |

| . . . . . . . |

| ak1 …… aki ……akj ……akn |

| . . . . . . . |

| an1 …… ani ……anj ……ann |

那么我们将从第r行到第k行的每一行中相同列的加起来,可以得到一个一维数组如下:

(ar1+……+ak1, ar2+……+ak2, ……,arn+……+akn)

由此我们可以看出最后所求的就是此一维数组的最大子断和问题,到此我们已经将问题转化为上面的已经解决了的问题了。

#include <stdio.h>
#include <string.h>

int r, c;
int a[110][110];
int num[110][110];

void change()
{//num[i][j]为第1行到第j行的对应行的数相加得到的数字
memset(num, 0, sizeof(num));
int i, j;
for(i = 1; i <= r; i++)
for(j = 1; j <= c; j++)
num[i][j] = num[i - 1][j] + a[i][j];
}

int main (void)
{
int t;
scanf("%d", &t);
while(t --)
{
scanf("%d %d", &r, &c);
int i, j, k;
for(i = 1; i <= r; i++)
for(j = 1; j <= c; j++)
scanf("%d", &a[i][j]);
change();
int sum = 0;
int max = -10000000;
for(i = 1; i <= r; i++)
{
for(j = i; j <= r; j++)
{
sum = 0;
//枚举每个一维数组,对一维的数字求最大子段和
for(k = 1; k <= c; k++)
{
if(sum > 0)
sum += num[j][k] - num[i - 1][k];
//num[j][k] - num[i - 1][k]为第i行到第j行的对应行的数相加得到的和
else
sum = num[j][k] - num[i - 1][k];
if(max < sum)
max = sum;
}
}
}
printf("%d\n", max);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: