Algorithm 求所有矩形面积的算法
假设我们得到4个点的矩形:它们的(x1,y1),…,(x4,y4) 我们要计算它们覆盖的总面积。我们要计算总面积,如果更多的矩形重叠,我们只计算一次这个面积 我并不是真的在寻找完成的解决方案,伪代码或一些算法和数据结构的链接在这里有用将不胜感激 矩形的形式是:由三个整数给出:左位置、右位置和高度。例如: L:0R:2H:2 L:1 R:3 H:3 L:-1R:4H:1 总面积为:10 x轴的最大值从-1e9到1e9,从x=L开始,到x=R结束Algorithm 求所有矩形面积的算法,algorithm,Algorithm,假设我们得到4个点的矩形:它们的(x1,y1),…,(x4,y4) 我们要计算它们覆盖的总面积。我们要计算总面积,如果更多的矩形重叠,我们只计算一次这个面积 我并不是真的在寻找完成的解决方案,伪代码或一些算法和数据结构的链接在这里有用将不胜感激 矩形的形式是:由三个整数给出:左位置、右位置和高度。例如: L:0R:2H:2 L:1 R:3 H:3 L:-1R:4H:1 总面积为:10 x轴的最大值从-1e9到1e9,从x=L开始,到x=R结束 y不能小于0,并且始终从y=0开始,到y=H结束。让
y不能小于0,并且始终从y=0开始,到y=H结束。让我们假设矩形的整数坐标范围非常小,比如说0到10。然后,一种简单的方法是创建网格并在其上绘制矩形: 占用的“像素”可以存储在一个集合中,也可以是位图中的设置位。当矩形重叠时,交叉点仅被标记为再次被占用,因此仅对区域贡献一次。面积是被占用单元的数量 对于大维度,数据结构将变得太大。此外,绘制几百万像素宽的矩形也会很慢 但当我们使用压缩坐标时,这种技术仍然可以应用。然后,网格只有矩形的实际坐标。单元格的宽度和高度可变。单元格的数量取决于矩形的数量,但与最小和最大坐标无关: 算法如下所示:
- 找到所有唯一的x坐标。按升序对它们进行排序,并将(坐标、索引)对存储在字典中以便于查找
- 对y坐标执行相同的操作
- 绘制矩形:找到x和y范围的索引并占据它们之间的单元格
- 通过将所有占用单元的面积相加来计算面积
SL = <empty> // sweep line
x0 = EL.first.left // leftmost x among all rectangle edges
lastX = x0
for each event E in EL // process events left-to-right
Let y0 = if SL.isEmpty then 0 else SL.first.height // current y
if E.ID in SL // event in SL means sweep line is at rectangle's right edge
remove E.ID from SL
else // event means sweep line is a new rectangle's left edge
add E.ID to SL
Let y1 = if SL.isEmpty then 0 else SL.first.height // new y
if y1 != y0
output line seg (lastX, y0) -> (E.x, y0)
output line seg (E.x, y0) -> (E.x, y1)
lastX = E.x
output final line seg (lastX, 0) -> (x0, 0)
SL=//扫描线
x0=EL.first.left//所有矩形边中最左边的x
lastX=x0
对于EL/中的每个事件E,从左到右处理事件
设y0=如果SL.isEmpty,则0 else SL.first.height//当前y
若SL中的E.ID//则SL中的事件表示扫描线位于矩形的右边缘
从SL中删除E.ID
else//event表示扫描线是新矩形的左边缘
将E.ID添加到SL
设y1=如果SL.isEmpty,则0 else SL.first.height//new y
如果y1!=y0
输出线分段(lastX,y0)->(E.x,y0)
输出线seg(E.x,y0)->(E.x,y1)
lastX=E.x
输出最终行seg(lastX,0)->(x0,0)
因为这听起来像是家庭作业或是面试问题,所以我将让您修改此算法,以提供扫掠形状的区域,而不是绘制其边缘
添加
只是为了好玩:
import java.util.ArrayList;
import static java.lang.Integer.compare;
import static java.util.Arrays.stream;
import static java.util.Collections.sort;
import java.util.Comparator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
class SkyLine {
static class Rectangle {
final int left;
final int right;
final int height;
Rectangle(int left, int right, int height) {
this.left = left;
this.right = right;
this.height = height;
}
}
static class Event implements Comparable<Event> {
final int x;
final int id;
public Event(int x, int id) {
this.x = x;
this.id = id;
}
@Override
public int compareTo(Event e) { return compare(x, e.x); }
}
final List<Rectangle> rectangles = new ArrayList<>();
final Comparator byHeightDescending =
(Comparator<Integer>) (Integer a, Integer b) ->
compare(rectangles.get(b).height, rectangles.get(a).height);
final SortedSet<Integer> scanLine = new TreeSet<>(byHeightDescending);
final List<Event> events = new ArrayList<>();
SkyLine(Rectangle [] data) {
stream(data).forEach(rectangles::add);
int id = 0;
for (Rectangle r : rectangles) {
events.add(new Event(r.left, id));
events.add(new Event(r.right, id));
++id;
}
sort(events);
}
int area() {
int area = 0;
Event ePrev = null;
for (Event e : events) {
if (ePrev != null) area += (e.x - ePrev.x) * rectangles.get(scanLine.first()).height;
if (!scanLine.remove(e.id)) scanLine.add(e.id);
ePrev = e;
}
return area;
}
public static void main(String [] args) {
Rectangle [] data = {
new Rectangle(0, 2, 2),
new Rectangle(1, 3, 3),
new Rectangle(-1, 4, 1),
};
int area = new SkyLine(data).area();
System.out.println(area);
}
}
import java.util.ArrayList;
导入静态java.lang.Integer.compare;
导入静态java.util.Arrays.stream;
导入静态java.util.Collections.sort;
导入java.util.Comparator;
导入java.util.List;
导入java.util.SortedSet;
导入java.util.TreeSet;
类天际线{
静态类矩形{
最后的整数左;
最终权利;
最终整数高度;
矩形(整数左、整数右、整数高){
this.left=左;
这个。右=右;
高度=高度;
}
}
静态类事件实现了可比较的{
最终整数x;
最终int id;
公共事件(整数x,整数id){
这个.x=x;
this.id=id;
}
@凌驾
公共int比较(事件e){返回比较(x,e.x);}
}
最终列表矩形=新的ArrayList();
最终比较器按高度递减=
(比较器)(整数a、整数b)->
比较(矩形.获取(b).高度,矩形.获取(a).高度);
最终分拣集扫描线=新树集(通过高度下降);
最终列表事件=新的ArrayList();
天际线(矩形[]数据){
流(数据).forEach(矩形::add);
int id=0;
用于(矩形r:矩形){
添加(新事件(右左,id));
添加(新事件(右,id));
++身份证;
}
排序(事件);
}
内部区域(){
int面积=0;
事件ePrev=null;
对于(事件e:事件){
如果(ePrev!=null)区域+=(e.x-ePrev.x)*矩形.get(scanLine.first()).height;
如果(!scanLine.remove(e.id))scanLine.add(e.id);
ePrev=e;
}
返回区;
}
公共静态void main(字符串[]args){
矩形[]数据={
新矩形(0,2,2),
新矩形(1,3,3),
新矩形(-1,4,1),
};
int area=新的天际线(数据).area();
系统输出打印LN(面积);
}
}
这个问题可能更适合于。您的问题不清楚,您是在谈论矩形的离散化还是什么?通常情况下,如果矩形R1已排序(从左下到右上)坐标x11、y11、x12、y12和R2 x21、y21、x22、y22,则如果它们重叠(x21所有矩形轴是否对齐(y1=y2;y3=y4;x2=x3和x1=x4)?是否