HDOJ To The Max 1081【动态规划-详解求最大子矩阵】

To The Max

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 9879    Accepted Submission(s): 4762

Problem Description

Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous sub-array of size 1 x 1 or greater located within the whole array. The sum of a rectangle is the sum of all the elements in that rectangle. In this problem the
sub-rectangle with the largest sum is referred to as the maximal sub-rectangle.

As an example, the maximal sub-rectangle of the array:

0 -2 -7 0

9 2 -6 2

-4 1 -4 1

-1 8 0 -2

is in the lower left corner:

9 2

-4 1

-1 8

and has a sum of 15.

Input

The input consists of an N x N array of integers. The input begins with a single positive integer N on a line by itself, indicating the size of the square two-dimensional array. This is followed by N 2 integers separated by whitespace (spaces and newlines).
These are the N 2 integers of the array, presented in row-major order. That is, all numbers in the first row, left to right, then all numbers in the second row, left to right, etc. N may be as large as 100. The numbers in the array will be in the range [-127,127].

Output

Output the sum of the maximal sub-rectangle.

Sample Input

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

Sample Output

15

经典动态规划:

求最大子矩阵。

解题思路:

①主要是先会求一维的,然后把二维的看成一维的计算即可。递推公式: d [ i ][ j ] 代表的 i 是起始行,j 是终止行。把i-j行进行捆绑,然后考虑成一维的即可。

先看一维是怎么算的,设有数组a0,a1…an,找除其中连续的子段,使它们的和达到最大。

假如,t[i]表示以ai结尾的子段中的最大子段和。

在已知t[i]的情况下,求t[i+1]的方法是:

如果t[i]>0, t [i+1]= t[i]+ai(继续在前一个子段上加上ai),否则t[i+1]=ai(不加上前面的子段),也就是说

状态转移方程为:

t[i] = (t[i-1]>0?t[i-1]:0)+a[i];

②只要求出一维的,二维的如果我们知道如何进行捆绑那么这题就可以解决了。

由于是 2 3 4行,所以我们可以将这3行”捆绑”起来,变为求 4(9-4-1),11(8+2+1),-10(-6-4+0),7(7+2-2)的最大子段和,ok,问题成功转化为一维的情况!然后就按一维求解即可。

③捆绑的时候就是i 到 j 行的所有同一列的元素相加之后的值,看成是一个一维上的值,然后我们就可以利用一维的状态转移方程进行求解了。

AC代码:

#include <stdio.h>
#include <math.h>
#include <vector>
#include <queue>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>

using namespace std;

const int INF = 0x3f3f3f3f;

int get(int f[110],int n)
{
	int t[110];
	int maxn=-99999999;
	memset(t,0,sizeof(t));
	for(int i=1;i<=n;i++)
	{
		t[i]=(t[i-1]>0?t[i-1]:0)+f[i];
		if(maxn<t[i])
			maxn=t[i];
	}
	return maxn;
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF){
        int f[110];
        int v[110][110];
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&v[i][j]);
            }
        }
        int ans=-99999999;
        for(int i=1;i<=n;i++){
            for(int j=i;j<=n;j++){
                memset(f,0,sizeof(f));
                for(int q=1;q<=n;q++){
                    for(int k=i;k<=j;k++)f[q]+=v[k][q];
                }
                ans=max(ans,get(f,n));
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

版权声明:本文为博主原创文章,转载请注明出处。

时间: 2024-10-23 12:48:34

HDOJ To The Max 1081【动态规划-详解求最大子矩阵】的相关文章

硬币问题-动态规划详解

基本动态规划之硬币问题 问题描述 假设有 1 元,3 元,5 元的硬币若干(无限),现在需要凑出 11 元,问如何组合才能使硬币的数量最少? 问题分析 乍看之下,我们简单的运用一下心算就能解出需要 2 个 5 元和 1 个 1 元的解.当然这里只是列出了这个问题比较简单的情况.当硬币的币制或者种类变化,并且需要凑出的总价值变大时,就很难靠简单的计算得出结论了.贪心算法可以在一定的程度上得出较优解,但不是每次都能得出最优解. 这里运用动态规划的思路解决该问题.按照一般思路,我们先从最基本的情况来一

c++的下降路径最短和----&gt;动态规划详解

#include <iostream> #include <vector> #include <algorithm> using namespace std; /*** * 分析:<----最优化问题----->此题用动态规划去写 * 1.第一步确定状态---->直接用它自己本身去写A[n][c] * 表示从第n层的第c个元素往下的最下的距离 * 2.第二步确定状态转移方程 * 状态转移方程可以分为三个部分 * 1.当c==0的时候 * A[n][c]

WP8.1开发:后台任务详解(求推荐)

小梦今天给大家分享一下windows phone 8.1中的后台任务如何实现,许多应用都会用到后台任务,所以我们必须得掌握. 新建后台任务类: 首先我们先新建一个windows phone 8.1空白应用程序.然后请右键单击你的解决方案并依此选择“添加”->“新建项目”.选择 Windows 运行时组件项目类型,为该项目命名为Basktask.(名字都随便起了,只是为了后面方便) 在项目中,右键单击“引用”并选择“添加新引用”.在“解决方案”下,选择“项目”,然后选择Basktask. 将Bas

HDU 1024 Max Sum Plus Plus【动态规划求最大M子段和详解 】

Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 29942    Accepted Submission(s): 10516 Problem Description Now I think you have got an AC in Ignatius.L's "Max Sum" problem

(转)dp动态规划分类详解

dp动态规划分类详解 转自:http://blog.csdn.NET/cc_again/article/details/25866971 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间效率高,代码量少,多元性强,主要考察思维能力.建模抽象能力.灵活度. ****************************************************************************************** 动态规划(英语:Dynamic programm

动态规划之最长递增子序列问题详解

最近重新开始看动态规划,动态规划算法的有效性依赖于问题本身所具有的两个重要性质:最优子结构性质和子问题重叠性质. 1.最优子结构:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质. 2.重叠子问题:在用递归算法自顶向下解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次.动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后尽可能多地利用这些子问题的解. (二).动态规划算法的基本步骤设计一个标准的动态规划算法,通常

Is It A Tree?------HDOJ杭电1325(两种方法,可以用也可以不用并查集!!!!!!详解)

Problem Description A tree is a well-known data structure that is either empty (null, void, nothing) or is a set of one or more nodes connected by directed edges between nodes satisfying the following properties. There is exactly one node, called the

动态规划01背包问题(例子详解)

附上原文地址:http://www.cnblogs.com/sdjl/articles/1274312.html ----第一节----初识动态规划-------- 经典的01背包问题是这样的: 有一个包和n个物品,包的容量为m,每个物品都有各自的体积和价值,问当从这n个物品中选择多个物品放在包里而物品体积总数不超过包的容量m时,能够得到的最大价值是多少?[对于每个物品不可以取多次,最多只能取一次,之所以叫做01背包,0表示不取,1表示取] 为了用一种生动又更形象的方式来讲解此题,我把此题用另一

57. 数对之差的最大值:4种方法详解与总结[maximum difference of array]

[本文链接] http://www.cnblogs.com/hellogiser/p/maximum-difference-of-array.html [题目] 在数组中,数字减去它右边的数字得到一个数对之差.求所有数对之差的最大值.例如在数组{2, 4, 1, 16, 7, 5, 11, 9}中,数对之差的最大值是11,是16减去5的结果. [分析] 看到这个题目,很多人的第一反应是找到这个数组的最大值和最小值,然后觉得最大值减去最小值就是最终的结果.这种思路忽略了题目中很重要的一点:数对之差