题目:求给出的多个相框的总覆盖面积。
这些相框可能重叠,也可能嵌套。每个相框给出外框和内框的左下角坐标和右上角坐标。
假设坐标二维体系为:屏幕左下角是原点(0,0),屏幕右上角为(+∞,+∞)。外框左下角(x1,y1),外框右上角(x2,y2),内框左下角(x3,y3),内框右上角(x4,y4)。一定满足x1<x3<=x4<x2 , y1<y3<=y4<y2。
例如要求相框1(1,1),(10,8),( 2,2),(9,7)和相框2 (7,5),(12,10),(8, 6),(11,9)覆盖的面积。
程序代码:
MAXN=16 #假设屏幕右上角尽头是(16,16),可以根据数据调整这个大小
tree=[0]*MAXN*4 #数组结构的线段树。线段树记录i节点对应的区间被多条线段覆盖。根节点序号为1。左孩子节点序号i*2,有孩子i*2+1。
line=[0]*MAXN*4 #数组结构的线段树。扫描到某个坐标y时,所在水平位置所有线段覆盖的水平长度。根节点序号为1。左孩子节点序号i*2,有孩子i*2+1。
class edgenode:
def __init__(self, x1=0, x2=0, y=0, d=0):
self.x1=x1
self.x2=x2
self.y=y
self.d=d
def __lt__(self, other):#重载定义比较函数,下面sort()调用中按此排序
if(self.y==other.y):
return self.d>other.d
else:
return self.y<other.y
m=0
din=[[1,1,10,8, 2,2,9,7], #第一个相框的外边框左下角坐标(1,1)外边框右上角坐标(10,8)内边框左下角(2,2)内边框右上角(9,7)
[7,5,12,10,8, 6,11,9] #第二个相框
]
#g=[edgenode(0,0,0)]*MAXN*8
g=[] #线段节点列表,存储排列好的线段
def add_edge(x1, x2, y, d):
global m
global g
m+=1
g.append(edgenode(x1, x2, y, d))
#g[m].x1=x1
#g[m].x2=x2
#g[m].y=y
#g[m].d=d
def init():
global m
global g
m=0
for i in range(len(din)):
x1=din[i][0]
y1=din[i][1]
x2=din[i][2]
y2=din[i][3]
x3=din[i][4]
y3=din[i][5]
x4=din[i][6]
y4=din[i][7]
if(x1!=x3):
add_edge(x1, x3, y1, 1)
if(x1!=x3):
add_edge(x1, x3, y2, -1)
if(x4!=x2):
add_edge(x4, x2, y1, 1)
if(x4!=x2):
add_edge(x4, x2, y2, -1)
add_edge(x3, x4, y1, 1)
add_edge(x3, x4, y3, -1)
add_edge(x3, x4, y4, 1)
add_edge(x3, x4, y2, -1)
#g_tmp=g[:]
#g_tmp2= sorted(g_tmp, key=attrgetter('y', 'd'))
g_tmp2= sorted(g)
g=[edgenode(0,0,0,0)]+g_tmp2
def tree_add(v, s, t, a, b, d): #若d=1表示插入线段[a,b],若d=-1表示减去线段[a,b]
global tree
global line
if(a<=s and t<=b):
tree[v]+=d
if(tree[v]>0):
line[v]=t-s
else:
if(t-s==1):
line[v]=0
else:
line[v]=line[v*2]+line[v*2+1]
else:
mid=(s+t)//2
if(a<mid):
tree_add(v*2, s, mid, a, b, d)
if(b>mid):
tree_add(v*2+1, mid, t, a, b, d)
if(tree[v]==0):
line[v]=line[v*2]+line[v*2+1]
else:
line[v]=t-s
def work():
global line
area=0
i=1
while(i<=m):
j=i
while(j<=m and g[j].y==g[i].y):
tree_add(1, 0, MAXN-1, g[j].x1, g[j].x2, g[j].d) #在此y的水平位置,加上线段[x1,x2],更新线段树所有需要更新的节点
j+=1
if(j<=m):
area+=line[1]*(g[j].y-g[i].y) #计算两个相邻水平位置线段覆盖的面积,并累加
i=j
print("line[]=")
for i in range(len(line)):
print(line[i], end=' ') #不自动换行
print("\nlen(line)=%d" %len(line))
print("area= %d\n" % area) #最终的答案,所有相框覆盖的面积
def mainfun():
init()
work()