c++動態規劃類算法編程彙總(四)集合的子集|最長子序列(矩陣)的和(積) | 最大子矩陣

目錄

一、集合的子集合

1.1 回溯法思路

1.2 回溯法代碼及解析

1.3 其他人思路及代碼供參考

1.4 分治法(動態規劃)

1.5 位運算法實現窮舉

二、連續子數組的最大和

2.1 類似股票最大值

2.2 推算方法

2.3 動態規劃方法

三、最大子矩陣和

3.1 題幹

3.2 錯誤的積分圖的方法

3.3 在連續子數組基礎上更改

四、直方圖中面積最大的矩形

4.1 題幹

4.2 思路

4.3 解答

五、最大全1子矩陣

5.1 投影法

5.2 分解爲面積最大的直方圖子問題


一、集合的子集合

給定一組不含重複元素的整數數組 nums,返回該數組所有可能的子集(冪集)。

oj:https://leetcode-cn.com/problems/subsets/

1.1 回溯法思路

回溯法及思路

  • 回溯法:回溯法又稱試探法,有點類似於枚舉法。
  • 採用深度優先遍歷,從根節點出發,遞歸地搜索解空間樹,直到找到解或者最後窮盡解空間樹後返回。
  • 函數停止的條件是達到空間數的葉子節點,未達到葉子節點則依次遍歷左子樹和右子樹。

本題的回溯法算法設計如圖所示:

1.2 回溯法代碼及解析

下面代碼及思路解析:

  • 通過current_set變量來存儲當前是否加入的矩陣
  • 深度優先遍歷,即先current_set不加num[loc],送入遞歸,再加上num[loc]送入遞歸
  • 遞歸中止之前,需要將當前的vector進行insert,因爲當前insert是上一個遞歸中加或者不加num[loc]送進來的變量,因此有必要先insert,再進行判斷中止。
  • 用set<vector<int>>可以節省重複,減少時間,簡化代碼量,但是會提升相應的運算消耗與存儲消耗,因此可以用更見的的,直接用vector<vector<int>>來實現的方法
  • 遞歸中,對當前current_set進行push_back操作之後,一定要pop_back,即使在程序的結尾。因爲本次遞歸會被上層函數調用,因此程序運行完成的時候,返回到上層函數中的current_set沒有恢復原狀,會導致程序出錯。比如,下一步中在尾部加入3了,return,導致上一層調用中必然含有3
  • 後面會給出更精簡的代碼
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;

class Solution {
public:
	vector<vector<int>> subsets(vector<int>& nums) {
		vector<vector<int>>sub_sets;
		int length = nums.size();
		if (length < 1){
			vector<int> empty;
			sub_sets.push_back(empty);
			return sub_sets;
		}
		vector<int>current_set;
		set<vector<int>>all_sub_sets;
		find_all_subsets(nums, 0, current_set, all_sub_sets);
		for (auto item : all_sub_sets){
			sub_sets.push_back(item);
		}
		return sub_sets;
	}

	void find_all_subsets(vector<int>& nums, int loc, vector<int> &current_set, set<vector<int>> & all_sub_sets){
		all_sub_sets.insert(current_set);
		int length = nums.size();
		if (loc >= length){
			return;
		}
		find_all_subsets(nums, loc + 1, current_set, all_sub_sets);
		current_set.push_back(nums[loc]);
		find_all_subsets(nums, loc + 1, current_set, all_sub_sets);
		current_set.pop_back();
		return;
	}
};

int main(){
	vector<int>set = {1,2,3};
	Solution s1;
	vector<vector<int>>subsets_it = s1.subsets(set);
	for (auto sub_set : subsets_it){
		if (sub_set.empty())cout << endl;
		else{
			for (auto item : sub_set){
				cout << item << " ";
			}
			cout << endl;
		}
	}

	int end; cin >> end;
	return 0;
}

相對更精簡的代碼:

  • 此代碼直接不用set,而是用vector<vector<int>>來實現
  • 只在最後一步進行push_back,避免了重複的問題
  • 輸出結果如下,即上面圖中,遍歷後的順序
3
2
2 3
1
1 3
1 2
1 2 3
class Solution {
public:
	vector<vector<int>> subsets(vector<int>& nums) {
		vector<vector<int>>sub_sets;
		int length = nums.size();
		if (length < 1){
			vector<int> empty;
			sub_sets.push_back(empty);
			return sub_sets;
		}
		vector<int>current_set;
		find_all_subsets(nums, 0, current_set, sub_sets);
		return sub_sets;
	}

	void find_all_subsets(vector<int>& nums, int loc, vector<int> &current_set, vector<vector<int>> & all_sub_sets){
		int length = nums.size();
		if (loc == length){
			all_sub_sets.push_back(current_set);
			return;
		}
		find_all_subsets(nums, loc + 1, current_set, all_sub_sets);
		current_set.push_back(nums[loc]);
		find_all_subsets(nums, loc + 1, current_set, all_sub_sets);
		current_set.pop_back();
		return;
	}
};

1.3 其他人思路及代碼供參考

作者:yi-shi-yi-mu-zi

鏈接:https://leetcode-cn.com/problems/subsets/solution/fen-zhi-fa-ji-qi-die-dai-xun-huan-shi-xian-he-di-g/

來源:力扣(LeetCode)

https://leetcode-cn.com/problems/subsets/solution/fen-zhi-fa-ji-qi-die-dai-xun-huan-shi-xian-he-di-g/

  • 以下代碼在執行過程中,只進行了在加入元素之後的push_back
  • 所以需要在初始位置進行push_back空集合
void  compute(vector<vector<int>>&subset_set,
              vector<int>& nums,vector<int>&now_set,int i){
    
    if(i>=nums.size()){
        return;
    }
    now_set.push_back(nums[i]);
    subset_set.push_back(now_set);
    compute(subset_set,nums,now_set,i+1);   
    now_set.pop_back();
    compute(subset_set,nums,now_set,i+1);
    return;
}

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>>subset_set;//保存最終結果
        vector<int>now_set={};
        subset_set.push_back(now_set);       
        compute(subset_set,nums,now_set,0);
        return subset_set;
    }
};

1.4 分治法(動態規劃)

分治思想,具體如下圖:

  • 假設沒有元素,則只有空集合的情況
  • 假設多了元素num[0],所有子集兩種情況:在空集合的基礎上一分爲二,一部分是空集合不含num[0],維持原狀,另一部分是空集合含num[0]
  • 假設多了num[1],則在num[0]已有的所有子集上一分爲二,一部分是已有num[0]的所有子集,不包含num[1],維持原狀,另一部分在原來num[0]的所有子集基礎上包含num[1]
  • 依次類推,num[n+1]的所有自己在num[n]的所有子集基礎上一分爲二。

也可以從動態規劃的角度來理解此代碼

  • 初始元素0個元素,所以空集合 set[0]={}
  • 有一個元素num[0],集合爲set[1]=set[0]+set[0].append(num[0])={}+{num[1]}
  • 已有n元素子集合的方案數目爲set[n]
  • 加入新元素,則新set[n+1]=set[n]+set[n].append(num[0])

根據如上思路寫出下面代碼:

class Solution {
public:
	vector<vector<int>> subsets(vector<int>& nums) {
		vector<vector<int>>result = { {} };
		//result.push_back({});
		int length = nums.size();
		if (length < 1)return result;
		for (int idx = 0; idx < length; idx++){
			int current = nums[idx];
			int copy_len = result.size();
			for (int idx_copy = 0; idx_copy < copy_len; idx_copy++){
				vector<int> copy = result[idx_copy];
				copy.push_back(current);
				result.push_back(copy);
			}
		}
		return result;
	}
};

注意事項:

  • 初始化空的二維數組,可以用:result = { {} }或者/result.push_back({})表示第一個元素爲空集合

1.5 位運算法實現窮舉

用二進制中數位來實現當前元素選中與否

  • 當前位與第幾個元素對應
  • 當前位爲1,則當前元素選中
  • 當前位爲0,則當前元素不選中

代碼實現:

  • long long int共64位,因此集合內元素上限爲64
  • 可以用爲了防止位運算& 與移位運算<<的優先級的問題,小心點加上括號
  • long long int也可以作爲地址取地址
class Solution {
public:
	vector<vector<int>> subsets(vector<int>& nums) {
		vector<vector<int>>result ;
		int length = nums.size();
		long long int mask = 0x0000000000000001;
		long long int top =( mask << length);
		for (long long int select = 0; select < top; select++){
			vector<int> sub;
			for (long long int num_item = 0; num_item < length; num_item++){
				if ((mask << num_item)&select){
					sub.push_back(nums[num_item]);
				}
			}
			result.push_back(sub);
		}
		
		return result;
	}
};

二、連續子數組的最大和

劍指offer P237

OJ:https://www.nowcoder.com/practice/459bd355da1549fa8a49e350bf3df484?tpId=13&tqId=11183&tPage=2&rp=3&ru=%2Fta%2Fcoding-interviews&qru=%2Fta%2Fcoding-interviews%2Fquestion-ranking

2.1 類似股票最大值

參考這個:c++策略類編程問題彙總 之中求股票最大值的算法

https://blog.csdn.net/weixin_36474809/article/details/100170310

  • 序列對於之前的所有的值在n位置累計爲 sum[n] 則子序列的值相當於 m到n的子序列的值相當於  sum[n]- sum[m-1]
  • 這就相當於求最大化sum[n]- sum[m-1]的問題,就是股票的最大利潤
#include<iostream>
#include<vector>
#include<deque>
using namespace std;

class Solution {
public:
	int FindGreatestSumOfSubArray(vector<int> array) {
		int length = array.size();
		if (length < 1)return 0;
		for (int idx = 1; idx < length; idx++){
			array[idx] += array[idx - 1];
		}
		int min = 0; 
		int max = array[0];
		for (int idx = 1; idx < length; idx++){
			int sum = array[idx] - min;
			if (sum>max)max = sum;
			if (array[idx] < min)min = array[idx];
		}
		return max;
	}
};

int main(){
	
	vector<int> array = { 6, -3, -2, 7, -15, 1, 2, 2 }; //out 8
	Solution s1;
	cout << s1.FindGreatestSumOfSubArray(array) << endl;
	int end; cin >> end;
	return 0;
}

2.2 推算方法

一個值用於存最大數值,另一個用於存當前sum,從左往右,如果前面sum小於0,則對於右邊來說,最大的右邊的子序列必然不包含其左邊的項。

這種方法顯然比上種方法簡單很多:

class Solution {
public:
	int FindGreatestSumOfSubArray(vector<int> array) {
		int length = array.size();
		if (length < 1)return 0;
		int max=0x80000000;
		int sum = 0;
		for (int idx = 0; idx < length; idx++){
			if (sum < 0)sum = array[idx];
			else sum += array[idx];
			if (max<sum)max = sum;
		}
		return max;
	}
};

2.3 動態規劃方法

可以從動態規劃的角度來理解上面的問題

  • f(i)表示包含data[i]的最大和子序列的和
  • 轉化就是,如果 data[i] >= 0, 則 f(i) = f(i-1) + data[i]
  • 如果 data[i] < 0, 則 f(i) = data[i]

程序寫法與上面一樣。

三、最大子矩陣和

博客:

https://blog.csdn.net/qq_41929449/article/details/79892086

OJ鏈接:

ZOJ Problem Set - 1074

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1074

https://zoj.pintia.cn/problem-sets/91827364500/problems/91827364573

來自 <https://www.cnblogs.com/GodA/p/5237061.html>

解析:

https://www.cnblogs.com/aabbcc/p/6504605.html

3.1 題幹

一個M*N的矩陣,找到此矩陣的一個子矩陣,並且這個子矩陣的元素的和是最大的,輸出這個最大的值。

例如:3*3的矩陣:
3
-1 3 -1
2 -1 3
-3 1 2
和最大的子矩陣是:
3 -1
-1 3
1 2
最大和是7

 

As an example, the maximal sub-rectangle of the array:
4
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.

3.2 錯誤的積分圖的方法

僅僅例程可以通過,想法不錯,但是仔細推導,發現錯了

採用了積分圖的方法,例程通過,但是OJ不過。吐槽下ZOJ,無法看到中間結果。

  • 積分圖中的值,相當於當前像素點中所有左,上,左上元素的和
  • 想當然的以爲,積分圖中右上積分值減去左下積分值,等於子矩陣的和(錯誤)
  • 例如紅框減去藍框,並非子矩陣的值,二是兩個長條狀的子矩陣的值。

#include<iostream>
#include<vector>
#include<deque>
#include<algorithm>
using namespace std;

int main(){

	int row, col; cin >> row; col = row;
	vector<int> each_col(col + 1);
	vector<vector<int>> matrix(row + 1, each_col);
	vector<vector<int>> min_matrix = matrix;
	//算積分圖,爲了方便運算,第0行和第0列設爲0,從1-row分別表示矩陣中的值
	//每個像素點的值是其左邊和上邊所有元素的和
	int max_value = 0;
	//轉換爲求其右上元素減去左下元素的最大值
	for (int idx_r = 1; idx_r <= row; idx_r++){
		for (int idx_c = 1; idx_c <= col; idx_c++){
			int current; cin >> current;
			matrix[idx_r][idx_c] = matrix[idx_r - 1][idx_c] + matrix[idx_r][idx_c - 1] - matrix[idx_r - 1][idx_c - 1] + current;
			min_matrix[idx_r][idx_c] = min(matrix[idx_r][idx_c], min(min_matrix[idx_r - 1][idx_c], min_matrix[idx_r][idx_c - 1]));
			int sub_max = matrix[idx_r][idx_c] - min_matrix[idx_r][idx_c];
			if (sub_max>max_value)max_value = sub_max;
		}
	}
	cout << max_value << endl;

	int end; cin >> end;
	return 0;
}

3.3 在連續子數組基礎上更改

如果對每個子矩陣進行求和比較,需要O((M*N)^2)的算法複雜度。顯然不能滿足要求

  • 對於一維問題,連續子數組的最大和的問題,已經解決過了。可以用O(n)實現求解
  • 但是連續子矩陣最大和的問題,可以分解爲連續子數組的最大和的問題。
  • 這樣在一個維度上可以算法複雜度漸少爲O(N),另一個維度上就依然是O(M^2),最終算法複雜度O(M*M*N)
  • 問題轉換:連續子矩陣的最大和=矩陣中連續的行的每一列求和爲一個一維數組,然後在一維數組之上求解一維數組的連續子序列的最大和

以下代碼完全通過

#include<iostream>
#include<vector>
#include<deque>
#include<algorithm>
using namespace std;

int main(){

	int row, col; cin >> row; col = row;
	vector<int> each_row(col);
	vector<vector<int>> matrix(row, each_row);
	for (int idx_r = 0; idx_r < row; idx_r++){
		for (int idx_c = 0; idx_c < col; idx_c++){
			cin >> matrix[idx_r][idx_c];
		}
	}
	int max_value = matrix[0][0];
	//先將當前up_row到down_row的和存爲一維數組,然後在一維數組上尋找
	for (int up_row = 0; up_row < row; up_row++){
		for (int down_row = up_row; down_row < row; down_row++){
			vector<int> row_sum(col, 0);
			for (int idx_r = up_row; idx_r <= down_row; idx_r++){
				for (int idx_c = 0; idx_c < col; idx_c++){
					row_sum[idx_c] += matrix[idx_r][idx_c];
				}
			}
			int sum = row_sum[0];
			for (int idx_c = 1; idx_c < col; idx_c++){
				if (sum < 0)sum = row_sum[idx_c];
				else{
					sum += row_sum[idx_c];
				}
				if (sum>max_value)max_value = sum;
			}
		}
	}

	cout << max_value << endl;

	int end; cin >> end;
	return 0;
}

四、直方圖中面積最大的矩形

Leetcode 84。OJ:

https://leetcode-cn.com/problems/largest-rectangle-in-histogram/

4.1 題幹

以上是柱狀圖的示例,其中每個柱子的寬度爲 1,給定的高度爲 [2,1,5,6,2,3]。問脂肪圖的最大矩形的面積。

輸入
6
2 1 5 6 2 3
輸出10

4.2 思路

如何根據一遍 遍歷O(N)找到當前柱子左邊第一個比它矮的柱子?即如何找出每個位置對應的left_min_loc的值。

  • 需要開闢一個數組left_min_loc,一個數組存儲左邊第一個比它矮的柱子。
  • 從左往右遍歷,如果右邊位置idx+1上的柱子比左邊idx位置的柱子長,則右邊柱子的向左第一個比它矮的柱子的位置就是idx,例如上面location爲2,3,5的柱子就是這麼得到的
  • 如果右邊位置idx+1上的柱子比左邊idx位置的柱子短,則需要與左邊柱子的left_min_loc進行比較,如果idx位置的柱子比left_min_loc位置的柱子長,則它的left_min_loc爲此值。如果當前idx的柱子依然比left_min_loc位置的柱子短,則繼續向left_min_loc位置的前面的left_min_loc的柱子進行比較。

4.3 解答

解答,注意等號的判斷。

  • while (right_min_loc != length && current_height <= heights[right_min_loc]  )語句中是<=,因爲等於的情況下,依然可以向左繼續推進。
  • 同時,需要加入判斷不等於length,不等於-1,不然就會內存溢出
#include<iostream>
#include<vector>
#include<deque>
#include<algorithm>
using namespace std;
class Solution {
public:
	int largestRectangleArea(vector<int>& heights) {
		int length = heights.size();
		if (length < 1)return 0;
		vector<int>most_left_min(length); most_left_min[0] = -1;
		vector<int>most_right_min(length); most_right_min[length - 1] = length;
		for (int idx = 1; idx < length; idx++){
			int current_height = heights[idx];
			if (current_height>heights[idx - 1]){
				most_left_min[idx] = idx - 1;
			}
			else{
				int left_min_loc = most_left_min[idx - 1];
				while (left_min_loc != -1 && current_height <= heights[left_min_loc]){
					left_min_loc = most_left_min[left_min_loc];
				}
				most_left_min[idx] = left_min_loc;
			}
		}
		//找到最右
		for (int idx = length - 2; idx >= 0; idx--){
			int current_height = heights[idx];
			if (current_height>heights[idx + 1]){
				most_right_min[idx] = idx + 1;
			}
			else{
				int right_min_loc = most_right_min[idx + 1];
				while (right_min_loc != length && current_height <= heights[right_min_loc]){
					right_min_loc = most_right_min[right_min_loc];
				}
				most_right_min[idx] = right_min_loc;
			}
		}
		int max_square = 0;
		for (int idx = 0; idx < length; idx++){
			int square = (most_right_min[idx] - most_left_min[idx] - 1)*heights[idx];
			if (square>max_square)max_square = square;
		}
		return max_square;
	}
};

int main(){
	/*
	6
	2 1 5 6 2 3
	//out 10
	12
	0 1 0 2 1 0 1 3 2 1 2 1
	out 6
	*/
	int length; cin >> length;
	vector<int> height(length);
	for (int idx = 0; idx < length; idx++){
		cin >> height[idx];
	}

	Solution s1;
	cout << s1.largestRectangleArea(height) << endl;
	//cout << max_value << endl;

	int end; cin >> end;
	return 0;
}

五、最大全1子矩陣

https://blog.csdn.net/huanghanqian/article/details/78771558

Leetcode 85 困難題

OJ:

https://leetcode-cn.com/problems/maximal-rectangle/

給定一個僅包含 0 和 1 的二維二進制矩陣,找出只包含 1 的最大矩形,並返回其面積。例如,輸入:

4 5
10100
10111
11111
10010
輸出: 6

如果只確定左上右下的矩陣邊,則需要對左上和右下進行遍歷,算法複雜度O(MN*MN)

5.1 投影法

  • 按行投影,遍歷行,行內的投影爲一行。全1則投影爲1,有0則投影爲0
  • 然後在行內找出1最寬的列,當前行列最大面積 行寬*列寬
  • 遍歷所有行並且進行投影算法複雜度爲O(M*M),求行內最寬列爲O(N),一共O(M*M*N),依然算法複雜度過高。
#include<iostream>
#include<vector>
#include<deque>
#include<algorithm>
using namespace std;

class Solution {
public:
	int maximalRectangle(vector<vector<char>>& matrix) {
		int row = matrix.size();
		if (row < 1)return 0;
		int col = matrix[0].size();
		int max_num1 = 0;
		for (int upper_row = 0; upper_row < row; upper_row++){
			for (int lower_row = upper_row; lower_row < row; lower_row++){
				vector<char>compresed_row(col, '1');
				int row_width = lower_row - upper_row + 1;
				// 把矩陣投影到每一行,均爲1纔是1
				for (int idx = upper_row; idx <= lower_row; idx++){
					for (int idxc = 0; idxc < col; idxc++){
						if (matrix[idx][idxc] == '0')compresed_row[idxc] = '0';
					}
				}
				// 針對每一行的投影,算出行寬度
				int col_width = 0;
				for (int idx = 0; idx < col; idx++){
					//矩陣存在,則將最大面積存入max_num1之中
					if (compresed_row[idx] == '1'){
						col_width++;
						if (col_width*row_width>max_num1)max_num1 = col_width*row_width;
					}
					else{
						col_width = 0;
					}
				}
			}
		}
		return max_num1;
	}
};


int main(){
	/*
	4 5
	10100
	10111
	11111
	10010
	out 6

	5 5
	11111
	11111
	11110
	11111
	11111
	//out 20
	*/
	int row, col; cin >> row >> col;
	vector<char>each_row(col);
	vector<vector<char>>matrix(row, each_row);
	for (int idx = 0; idx < row; idx++){
		for (int idxc = 0; idxc < col; idxc++){
			cin >> matrix[idx][idxc];
		}
	}
	Solution s1;
	cout << s1.maximalRectangle(matrix) << endl;
	//cout << max_value << endl;

	int end; cin >> end;
	return 0;
}

 

5.2 分解爲面積最大的直方圖子問題

  • 將矩陣中的子矩陣,轉換爲求柱狀圖的最長長方形。
  • 一次遍歷找到最長長方形的算法複雜度爲O(N)
  • 在每一行的基礎上往上找到最大的柱狀圖的長方形面積。
  • 算法複雜度O(MN)非常簡單
#include<iostream>
#include<vector>
#include<deque>
#include<algorithm>
using namespace std;

class Solution {
public:
	int maximalRectangle(vector<vector<char>>& matrix) {
		int row = matrix.size();
		if (row < 1)return 0;
		int col = matrix[0].size();
		if (col < 1)return 0;

		int max_area = 0;
		for (int idx_r = 0; idx_r < row; idx_r++){
			vector<int> col_tall(col, 0);
			//cout << "row_hist_gram:" << idx_r << endl;
			//cout << "col_tall" << endl;
			for (int idx_c = 0; idx_c < col; idx_c++){
				//統計出來當前行往上的直方圖
				for (int tall_r = idx_r; tall_r < row; tall_r++){
					if (matrix[tall_r][idx_c] == '1')col_tall[idx_c]++;
					else{
						//cout << col_tall[idx_c] << " ";
						break;
					}
				}
			}
			//cout << endl;
			vector<int>left_min_loc(col); left_min_loc[0] = -1;
			vector<int>right_min_loc(col); right_min_loc[col - 1] = col;
			//從左向右遍歷
			//cout << "left_min_loc:";
			for (int idx = 1; idx < col; idx++){
				int current_height = col_tall[idx];
				//比左邊大,則左邊位置即爲left_min_loc
				if (current_height>col_tall[idx - 1]){
					left_min_loc[idx] = idx - 1;
				}
				else{// <= 左邊,則可以左邊再向左延申
					int current_left_loc = idx - 1;
					while (current_left_loc != -1 && current_height <= col_tall[current_left_loc]){
						current_left_loc = left_min_loc[current_left_loc];
					}
					left_min_loc[idx] = current_left_loc;
				}
				//cout << left_min_loc[idx] << ' ';
			}
			//cout << endl;
			//從右向左遍歷
			//cout << "right_min_loc:";
			for (int idx = col - 2; idx >= 0; idx--){
				int current_height = col_tall[idx];
				//比右邊大,則右邊位置即爲right_min_loc
				if (current_height>col_tall[idx + 1]){
					right_min_loc[idx] = idx + 1;
				}
				else{// <= 右邊,則可以右邊再向右延申
					int current_right_loc = idx + 1;
					while (current_right_loc != col && current_height <= col_tall[current_right_loc]){
						current_right_loc = right_min_loc[current_right_loc];
					}
					right_min_loc[idx] = current_right_loc;
				}
				//cout << right_min_loc[idx] << ' ';
			}
			//cout << endl;
			for (int idx = 0; idx < col; idx++){
				int area = (right_min_loc[idx] - left_min_loc[idx] - 1)*col_tall[idx];
				//cout << area << ' ';
				if (area>max_area)max_area = area;
			}
		}
		//cout << endl;
		return max_area;
	}
};

int main(){
	/*
	4 5
	10100
	10111
	11111
	10010
	out 6

	5 5
	11111
	11111
	11110
	11111
	11111
	//out 20
	*/
	int row, col; cin >> row >> col;
	vector<char>each_row(col);
	vector<vector<char>>matrix(row, each_row);
	for (int idx = 0; idx < row; idx++){
		for (int idxc = 0; idxc < col; idxc++){
			cin >> matrix[idx][idxc];
		}
	}
	Solution s1;
	cout << s1.maximalRectangle(matrix) << endl;


	int end; cin >> end;
	return 0;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章