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;
}

 

 

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