[USACO5.3.2] 窗体面积 - 矩形切割

来源:互联网 发布:淘宝首页全屏怎么装修 编辑:程序博客网 时间:2024/05/21 08:37

题目描述

你刚刚接手一项窗体界面工程。窗体界面还算简单,而且幸运的是,你不必显示实际的窗体。有 5 种基本操作:

  创建一个新窗体
  将窗体置顶
  将窗体置底
  删除一个窗体
输出窗体可见部分的百分比(就是,不被其它窗体覆盖的部分)。
在输入文件中,操作以如下的格式出现。

  创建一个新窗体:w(I,x,y,X,Y)
  将窗体置顶: t(I)
  将窗体置底: b(I)
  删除一个窗体:d(I)
  输出窗体可见部分的百分比:s(I)
I 是每个窗体唯一的标识符。表示符可以是 ‘a’..’z’, ‘A’..’Z’ 和 ‘0’..’9’ 中的任何一个。输入文件中没有多余的空格。
(x,y)和(X,Y)是窗体的对角。当你创建一个窗体的时候,它自动被“置顶”。你不能用已经存在的标识符来创建窗体,但是你  可以删除一个窗体后再用已删除窗体的标识符来创建窗体。坐标用正整数来表示,并且所有的窗体面积都不为 0(x <> X 且 y <> Y)。x 坐标和 y 坐标在 1 —— 32767 的范围内。


输入格式

输入文件包含给你的解释程序的一系列命令,每行一个。当输入文件结束时,停止程序。


输出格式

只对于 s() 命令进行输出。当然,输入文件可能有许多 s() 命令,所以输出文件应该是一个百分比的序列,每行一个,百分比是窗体可见部分的百分比。百分比应该四舍五入到三位小数。


样例数据

样例输入

w(a,10,132,20,12)
w(b,8,76,124,15)
s(a)

样例输出

49.167


说明

插入操作不超过150
总操作次数不超过1000


题目分析

这应该算是usaco史上最为恶心的调试题了吧(当然素数方阵更厉害)
对于每一个窗体看做一个矩形
维护一个队列
新加的窗体加入队尾
如果要置顶一个窗体,将他从队列中转到队尾
如果要置底一个窗体,将他从队列中转到队首
如果删除一个窗体,将他从队列中删除
以上操作均不用加入切割

如果查询,那么将队列中所有窗体顺序进行切割,统计面积
查询完毕后清空矩形切割中的矩形


源代码

#include<algorithm>#include<iostream>#include<iomanip>#include<cstring>#include<cstdlib>#include<vector>#include<cstdio>#include<cmath>#include<queue>#include<map>using namespace std;inline const int Get_Int() {    int num=0,bj=1;    char x=getchar();    while(x<'0'||x>'9') {        if(x=='-')bj=-1;        x=getchar();    }    while(x>='0'&&x<='9') {        num=num*10+x-'0';        x=getchar();    }    return num*bj;}struct Square {    double x1,x2,y1,y2;    char uuid;    Square() {}    Square(double lx,double ly,double rx,double ry,char color):x1(lx),y1(ly),x2(rx),y2(ry),uuid(color) {}};struct Cut_Square {    Square a[100005];    int sum;    int init() {        sum=0;    }    bool if_intersect(Square a,Square b) {        if(a.x1>=b.x2||a.y1>=b.y2||a.x2<=b.x1||a.y2<=b.y1)return false;        else return true;    }    void add(double x1,double y1,double x2,double y2,char uuid) {        a[++sum]=Square(x1,y1,x2,y2,uuid);    }    void del(int index) {        a[index]=a[sum];        sum--;    }    double Xway_cut(int index,double x1,double y1,double x2,double y2) { //返回交集        double k1=max(x1,a[index].x1);        double k2=min(x2,a[index].x2);        if(a[index].x1<k1)add(a[index].x1,a[index].y1,k1,a[index].y2,a[index].uuid);        if(k2<a[index].x2)add(k2,a[index].y1,a[index].x2,a[index].y2,a[index].uuid);        return Yway_cut(index,k1,y1,k2,y2);    }    double Yway_cut(int index,double x1,double y1,double x2,double y2) {        double k1=max(y1,a[index].y1);        double k2=min(y2,a[index].y2);        if(a[index].y1<k1)add(x1,a[index].y1,x2,k1,a[index].uuid);        if(k2<a[index].y2)add(x1,k2,x2,a[index].y2,a[index].uuid);        return (x2-x1)*(k2-k1);    }};struct QueNode {    char uuid;    int x1,y1,x2,y2;    QueNode() {}    QueNode(char u,int lx,int ly,int rx,int ry):uuid(u),x1(lx),y1(ly),x2(rx),y2(ry) {}} Q[500005];Cut_Square s;int Right=0;int main() {    char order,uuid;    while(scanf("%c",&order)!=EOF) {        if(order=='w') { //加入            int x1,y1,x2,y2;            scanf("(%c,%d,%d,%d,%d)",&uuid,&x1,&y1,&x2,&y2);            int tx1=x1,ty1=y1,tx2=x2,ty2=y2;            x1=min(tx1,tx2);            y1=min(ty1,ty2);            x2=max(tx1,tx2);            y2=max(ty1,ty2);            Q[++Right]=QueNode(uuid,x1,y1,x2,y2); //窗体入队        } else if(order=='t') { //置顶            int pos;            scanf("(%c)",&uuid);            for(int i=1; i<=Right; i++) //移动队列,将指定窗口放到队尾                if(Q[i].uuid==uuid) {                    pos=i;                    break;                }            QueNode Now=Q[pos];            for(int i=pos; i<Right; i++)Q[i]=Q[i+1];            Q[Right]=Now;        } else if(order=='b') { //置底            int pos;            scanf("(%c)",&uuid);            for(int i=1; i<=Right; i++) //移动队列,将指定窗口放到队首                if(Q[i].uuid==uuid) {                    pos=i;                    break;                }            QueNode Now=Q[pos];            for(int i=pos-1; i>=1; i--)Q[i+1]=Q[i];            Q[1]=Now;        } else if(order=='d') { //删除            int pos;            scanf("(%c)",&uuid);            for(int i=1; i<=Right; i++)                if(Q[i].uuid==uuid) {                    pos=i;                    break;                }            for(int i=pos; i<Right; i++)Q[i]=Q[i+1];            Right--;        } else if(order=='s') { //询问            int pos;            double sum=0;            scanf("(%c)",&uuid);            for(int i=1; i<=Right; i++)                if(Q[i].uuid==uuid) {                    pos=i;                    break;                }            for(int i=1; i<=Right; i++) { //依次添加窗体                 Square b=Square(Q[i].x1,Q[i].y1,Q[i].x2,Q[i].y2,Q[i].uuid);                for(int j=1; j<=s.sum; j++) {                    if(!s.if_intersect(s.a[j],b))continue; //不相交                    s.Xway_cut(j,b.x1,b.y1,b.x2,b.y2);                    s.del(j);                    j--; //删除完矩形移动了最后一个矩形,若j不-1可能导致原矩形未切割                }                s.add(b.x1,b.y1,b.x2,b.y2,b.uuid);            }            for(int i=1; i<=s.sum; i++)                if(s.a[i].uuid==uuid)sum+=(s.a[i].x2-s.a[i].x1)*(s.a[i].y2-s.a[i].y1);            printf("%0.3lf\n",sum*100/((Q[pos].x2-Q[pos].x1)*(Q[pos].y2-Q[pos].y1)));            s.init(); //清空矩阵切割数组         }    }    return 0;}

0 0
原创粉丝点击