题目链接在此
题目理解都理解了半天。然后想了许多办法最终都夭折了。于是参考了这位大神(貌似是同级同班的同学)的代码。
自己重写了一遍。大体相近。里面有注释:
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
struct rectangle {
int x1, y1, x2, y2;
rectangle() {}
rectangle(int xx1, int yy1, int xx2, int yy2) :
x1(xx1), y1(yy1), x2(xx2), y2(yy2){}
};
// 自定义比较函数,依照x值对矩形排序
bool cmpX(rectangle a, rectangle b) {
return (a.x1 < b.x1) || (a.x1 == b.x1 && a.x2 < b.x2);
};
// 自定义比较函数,依照y值对矩形排序
bool cmpY(rectangle a, rectangle b){
return (a.y1 < b.y1) || (a.y1 == b.y1 && a.y2 < b.y2);
};
void cal(int length, int width, vector<rectangle>& vec, int& max_area) {
set<int> xs, ys;
for (vector<rectangle>::iterator it = vec.begin(); it != vec.end(); it++) {
xs.insert(it->x1);
xs.insert(it->x2);
ys.insert(it->y1);
ys.insert(it->y2);
}
// 若x和y的值都<=2,说明只剩一个矩形了,判断后返回
if (xs.size() <= 2 && ys.size() <= 2) {
max_area = max(max_area, length * width);
return;
}
/*竖切开始*/
sort(vec.begin(), vec.end(), cmpX); // 按x值进行排序
// 记录最左、最右两条竖边的x值
int leftMostX = *xs.begin();
int rightMostX = *(--xs.end());
// 删除最左、最右两条竖边,因为切了也没用
xs.erase(xs.begin());
xs.erase(--xs.end());
for (set<int>::iterator it = xs.begin(); it != xs.end(); it++) { // 遍历所有竖边
bool canCut = true; // 标记是否可以切
// 若恰好与某个矩形(指的是vec中的矩形)有交点,则不能切
for (vector<rectangle>::iterator iter = vec.begin(); iter != vec.end(); iter++) {
if (*it > iter->x1 && *it < iter->x2) {
canCut = false;
break;
}
}
// 可以切则将该竖边左右两部分的矩形分出来,再进行递归调用此函数
if (canCut) {
vector<rectangle> left, right;
for (vector<rectangle>::iterator iter = vec.begin(); iter != vec.end(); iter++)
iter->x2 <= *it ? left.push_back(*iter) : right.push_back(*iter);
cal(*it - leftMostX, width, left, max_area);
cal(rightMostX - *it, width, right, max_area);
return; // 切完竖边不用管横边
}
}
/*竖切结束*/
/*横切开始*/
sort(vec.begin(), vec.end(), cmpY); // 按y值进行排序
// 记录最上、最下两条横边的x值
int bottomY = *ys.begin();
int topY = *(--ys.end());
// 删除最上、最下两条横边,因为切了也没用
ys.erase(ys.begin());
ys.erase(--ys.end());
for (set<int>::iterator it = ys.begin(); it != ys.end(); it++) { // 遍历所有横边
bool canCut = true;
// 若恰好与某个矩形(指的是vec中的矩形)有交点,则不能切
for (vector<rectangle>::iterator iter = vec.begin(); iter != vec.end(); iter++) {
if (*it > iter->y1 && *it < iter->y2) {
canCut = false;
break;
}
}
// 可以切则将该横边上下两部分的矩形分出来,再进行递归调用此函数
if (canCut) {
vector<rectangle> down, up;
for (vector<rectangle>::iterator iter = vec.begin(); iter != vec.end(); iter++)
iter->y2 <= *it ? down.push_back(*iter) : up.push_back(*iter);
cal(length, *it - bottomY, down, max_area);
cal(length, topY - *it, up, max_area);
return; // 切完横边不用管竖边
}
}
/*横切结束*/
/*横边、竖边都无法切,则直接判断后返回*/
max_area = max(max_area, length * width);
}
int main() {
int testCase;
cin >> testCase;
while (testCase--) {
int max_area = 0;
int length, width, num;
int x1, y1, x2, y2;
vector<rectangle> vec; // 记录所有矩形
cin >> length >> width >> num;
while (num--) {
cin >> x1 >> y1 >> x2 >> y2;
vec.push_back(rectangle(x1,y1,x2,y2));
}
cal(length, width, vec, max_area);
cout << max_area << endl;
}
return 0;
}
本文介绍了一个关于矩形切割的问题及解决思路。通过自定义比较函数对矩形进行排序,并使用递归的方式尝试从竖直方向和水平方向切割矩形区域,以求得最大面积。
608

被折叠的 条评论
为什么被折叠?



