經典動態規劃: 尋找最大矩形 POJ1050
1050:To the Max
總時間限制: 5000ms 內存限制: 65536kB描述Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous sub-array of size 1*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 -2is in the lower left corner:9 2-4 1-1 8and has a sum of 15.輸入The input consists of an N * 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 500. The numbers in the array will be in the range [-127,127].
輸出Output the sum of the maximal sub-rectangle.樣例輸入40 -2 -7 0 9 2 -6 2-4 1 -4 1 -18 0 -2樣例輸出15來源
Greater New York 2001
原題鏈接:OpenJudge - 1050:To the Max
一、題意分析
題意翻譯過來就是,給你N^2個數字,構成一個矩陣,需要你從其中找出和最大的子矩陣。例如:
0 -2 -7 0
9 2 -6 2-4 1 -4 1-1 8 0 -2
這個矩陣中最大的子矩陣就是:
9 2
-4 1-1 8
其和為15,程序輸出15就可以了。
二、思路分析
咋一看,就有一種使用暴力枚舉法的衝動,但先別急,每當有這個想法時,必先冷靜分析一下:時間夠用?
注意到:
N may be as large as 500.
一個500*500的矩陣,其中的子矩陣數量是驚人的,時間雖然給了5000ms,但肯定不夠。
每當想用暴力的演算法解決問題,但時間又不夠的時候,咱們就可以開始考慮動態規划了。
這個問題可以分解成一個稍簡單的問題:
給你你一行數量為n的數組row[n],如何從中找出和最大的一段子數組?
我們可以這樣考慮:
用一個大小同樣為n的數組maxrow存儲以每個以row[i]結尾的最大子序列的和。
舉個例子:
如果:
row[5]={1,2,3,-7,5}
那麼:maxrow[0]=1maxrow[1]=1+2=3maxrow[2]=1+2+3=6maxrow[3]=1+2+3-7=-1maxrow[4]=5
可以發現:
maxrow[i]=maxrow[i-1]>0?maxrow[i-1]+row[i]:row[i];
maxrow中最大的那個元素就是我們要找的最大子序列的和。
回到原來的問題我們就會發現,它也可以化歸成同樣的問題:
一個數組即可看做行為1的矩陣,而矩陣通過行與行中每個元素的相加可以壓縮成一個數組。
N*N的矩陣可以組成1+2+3+……N個不同的數組,而最大的子矩陣之和就藏在其中某個數組的maxrow當中。
三、AC code
內存:2048kB 時間:231ms
#include <iostream>using namespace std;int board[501][501]{};int maxrow[501]{};int maxmatrix=0;int main(int argc, const char * argv[]) { int n; cin>>n; for(int i=0;i<n;i++)//input { for(int j=0;j<n;j++) { cin>>board[i][j]; } } int temprow[n]; for(int i=0;i<n;i++)//i for rows { for(int c=0;c<n;c++)//initialize { temprow[c]=0; } for(int j=i;j<n;j++)//j for rows { for(int c=0;c<n;c++)// c for cols { temprow[c]+=board[j][c]; } for(int c=0;c<n;c++) { if(c==0) { maxrow[c]=temprow[c]; }else{ maxrow[c]=maxrow[c-1]>0?maxrow[c-1]+temprow[c]:temprow[c]; } maxmatrix=max(maxmatrix,maxrow[c]); } } } cout<<maxmatrix<<endl;}
廣告時間啦~
理工狗不想被人文素養拖後腿?不妨關注微信公眾號:
為你讀最好的書~
推薦閱讀:
※動態規劃 1 ——基本概念
※動態規劃 3 ——一維狀態 背包問題
※強化學習——MDPs求解之動態規劃
※動態規劃 2 ——一維狀態 非降子序列問題