UVa 108|Maximum Sum|动态规划

来源:互联网 发布:windows水印在哪里 编辑:程序博客网 时间:2024/05/17 08:45

原题地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=44

题目翻译

通常一个在一维上很好解决的问题扩展到二维后就难解决多了。类似的还有2-SAT和3-SAT(NPC问题)。

给定一个二维数组,找出一个子矩阵最大化其个元素的和。

比如数组:

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

最左下角的一个子矩阵:

 9 2-4 1-1 8

的和15最大。

输入

第一行一个整数N(N100),表示二维数组的尺寸。
接下来N×N个数,每个数字间可以用空格或换行隔开。数组元素(127ai,j127)按从左到右,从上到下的顺序给出。

输出

一行一个整数,表示子矩阵的最大和。

样例输入

40 -2 -7 0 9 2 -6 2-4 1 -4 1 -18 0 -2

样例输出

15

题解

题目给了很明显的暗示。
我们考虑一维问题,给定一个数列,求最大子串和。对于已经求出的前缀和sumi,一个子串和可以表示为sumrsuml1,如果我们枚举r,只要知道一个最小的suml1即可。这个我们在扫sum的时候就可以顺便求了。

扩展到二维的话,我们考虑枚举一维,另一维仍按照上面的做法做。

#include <cstdio>#define FOR(i,j,k) for(i=j;i<=k;++i)const int N = 105;int mat[N][N], sum[N][N];int main() {    int n, i, j, k;    scanf("%d", &n);    FOR(i,1,n) FOR(j,1,n) {        scanf("%d", &mat[i][j]);        sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + mat[i][j];    }    int ans = 0x80000000;    FOR(i,1,n) FOR(j,1,i) { // j~i        int mi = 0;        FOR(k,1,n) {            int t = sum[i][k] - sum[j - 1][k] - mi;            if (t > ans) ans = t;            if (sum[i][k] - sum[j - 1][k] < mi)                mi = sum[i][k] - sum[j - 1][k];        }    }    printf("%d\n", ans);    return 0;}
原创粉丝点击