[NOI97] 卫星覆盖 - 矩形切割(立方体切割)


题目描述

SERCOI(Space-Earth Resource Cover-Observe lnstitute)是一个致力于利用卫星技术对空间和地球资源进行覆盖观测的组织。现在他们研制成功一种新型资源观测卫星-SERCOI-308。这种卫星可以覆盖空间直角坐标系中一定大小的立方体空间,卫星处于该立方体的中心。
  其中(x,y,z)为立方体的中心点坐标,r为此中心点到立方体各个面的距离(即r为立方体高的一半).立方体的各条边均平行于相应的坐标轴。我们可以用一个四元组(x,y,z,r)描述一颗卫星的状态,它所能覆盖的空间体积V=(2r)^3=8r^3。
  由于一颗卫星所能覆盖的空间体积是有限的,因此空间中可能有若干颗卫星协同工作。它们所覆盖的空间区域可能有重叠的地方,如下图所示(阴影部分表示重叠的区域)。
  写一个程序,根据给定的卫星分布情况,计算它们所覆盖的总体积。
  这里写图片描述


输入格式

输入文件的第一行是一个正整数N(1<=N<=10O):表示空间中的卫星总数。接下来的N行每行给出了一颗卫星的状态,用空格隔开的四个正整数x,y,z,r依次表示了该卫星所能覆盖的立方体空间的中心点坐标和半高,其中-1000<=x,y,z<=1000, 1<=r<=200。


输出格式

输出文件只有一行,包括一个正整数,表示所有这些卫星所覆盖的空间总体积。


样例数据

样例输入

3
0 0 0 3
1 –1 0 1
19 3 5 6

样例输出

1944


题目分析

好的
写三维矩形切割吧
顺便用通用切割搞搞,改个维度就可以过


源代码

通用切割

#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
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;
}
const int maxn=3;
struct Cube {
    double left[maxn],right[maxn];
} ;
struct Universal_Cut {
    Cube a[10005];
    int sum;
    int init() {
        sum=0;
    }
    bool if_intersect(Cube a,Cube b) {
        for(int i=0; i<maxn; i++)
            if(a.left[i]>=b.right[i]||a.right[i]<=b.left[i])return false;
        return true;
    }
    void add(double x[maxn],double y[maxn]) {
        sum++; 
        for(int i=0; i<maxn; i++) {
            a[sum].left[i]=x[i]; 
            a[sum].right[i]=y[i];
        }
    }
    void del(int index) {
        a[index]=a[sum];
        sum--;
    }
    void cut(Cube a,Cube b,int dimension) { //返回交集
        if(dimension==maxn)return;
        double k1=max(a.left[dimension],b.left[dimension]);
        double k2=min(a.right[dimension],b.right[dimension]);
        if(a.left[dimension]<k1) {
            Cube tmp=a;
            tmp.right[dimension]=k1;
            add(tmp.left,tmp.right);
        }
        if(k2<a.right[dimension]) {
            Cube tmp=a;
            tmp.left[dimension]=k2;
            add(tmp.left,tmp.right);
        }
        a.left[dimension]=k1;
        a.right[dimension]=k2;
        cut(a,b,dimension+1);
    }
};
Universal_Cut c;
int n,ans=0;
double Bleft[maxn],Bright[maxn];
int main() {
    n=Get_Int();
    for(int i=1; i<=n; i++) {
        int x=Get_Int(),y=Get_Int(),z=Get_Int(),h=Get_Int();
        Bleft[0]=x-h,Bleft[1]=y-h,Bleft[2]=z-h,Bright[0]=x+h,Bright[1]=y+h,Bright[2]=z+h;
        Cube b;
        for(int i=0; i<maxn; i++) {
            b.left[i]=Bleft[i];
            b.right[i]=Bright[i];
        }
        for(int j=1; j<=c.sum; j++) {
            if(!c.if_intersect(c.a[j],b))continue;
            c.cut(c.a[j],b,0);
            c.del(j);
            j--;
        }
        c.add(Bleft,Bright);
    }
    for(int i=1; i<=c.sum; i++) {
        int tmp=1;
        for(int j=0; j<maxn; j++)
            tmp*=c.a[i].right[j]-c.a[i].left[j];
        ans+=tmp;
    }
    printf("%d\n",ans);
    return 0;
}

三维切割

#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
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 Cube {
    double x1,x2,y1,y2,z1,z2;
    Cube() {}
    Cube(double lx,double ly,double lz,double rx,double ry,double rz):x1(lx),y1(ly),z1(lz),x2(rx),y2(ry),z2(rz) {}
} ;
struct Cut_Cube {
    Cube a[10005];
    int sum;
    int init() {
        sum=0;
    }
    bool if_intersect(Cube a,Cube b) {
        if(a.x1>=b.x2||a.y1>=b.y2||a.z1>=b.z2||a.x2<=b.x1||a.y2<=b.y1||a.z2<=b.z1)return false;
        else return true;
    }
    void add(double x1,double y1,double z1,double x2,double y2,double z2) {
        a[++sum]=Cube(x1,y1,z1,x2,y2,z2);
    }
    void del(int index) {
        a[index]=a[sum];
        sum--;
    }
    double Xway_cut(int index,double x1,double y1,double z1,double x2,double y2,double z2) { //返回交集 
        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,a[index].z1,k1,a[index].y2,a[index].z2);
        if(k2<a[index].x2)add(k2,a[index].y1,a[index].z1,a[index].x2,a[index].y2,a[index].z2);
        return Yway_cut(index,k1,y1,z1,k2,y2,z2);
    }
    double Yway_cut(int index,double x1,double y1,double z1,double x2,double y2,double z2) {
        double k1=max(y1,a[index].y1);
        double k2=min(y2,a[index].y2);
        if(a[index].y1<k1)add(x1,a[index].y1,a[index].z1,x2,k1,a[index].z2);
        if(k2<a[index].y2)add(x1,k2,a[index].z1,x2,a[index].y2,a[index].z2);
        return Zway_cut(index,x1,k1,z1,x2,k2,z2);
    }
    double Zway_cut(int index,double x1,double y1,double z1,double x2,double y2,double z2) {
        double k1=max(z1,a[index].z1);
        double k2=min(z2,a[index].z2);
        if(a[index].z1<k1)add(x1,y1,a[index].z1,x2,y2,k1);
        if(k2<a[index].z2)add(x1,y1,k2,x2,y2,a[index].z2);
    }
};
Cut_Cube c;
int n,ans=0;
int main() {
    n=Get_Int();
    for(int i=1; i<=n; i++) {
        int x=Get_Int(),y=Get_Int(),z=Get_Int(),h=Get_Int();
        int x1=x-h,x2=x+h,y1=y-h,y2=y+h,z1=z-h,z2=z+h;
        Cube b(x1,y1,z1,x2,y2,z2);
        for(int j=1; j<=c.sum; j++) {
            if(!c.if_intersect(c.a[j],b))continue;
            c.Xway_cut(j,x1,y1,z1,x2,y2,z2);
            c.del(j);
            j--;
        }
        c.add(x1,y1,z1,x2,y2,z2);
    }
    for(int i=1; i<=c.sum; i++)ans+=(c.a[i].x2-c.a[i].x1)*(c.a[i].y2-c.a[i].y1)*(c.a[i].z2-c.a[i].z1);
    printf("%d\n",ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值