相框的覆盖面积

题目:求给出的多个相框的总覆盖面积。

这些相框可能重叠,也可能嵌套。每个相框给出外框和内框的左下角坐标和右上角坐标。

假设坐标二维体系为:屏幕左下角是原点(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()
        
    

猜你喜欢

转载自blog.csdn.net/william_djj/article/details/87304099