UVA12171_Sculpture_坐标旋转45度映射&&离散化

题意

某雕塑有 n 个边长平行于坐标轴的长方体组成。用每个长方体左上角的坐标,以及长方体的长宽高表示每个长方体。要求统计这个长方体的体积和表面积。其中,体积包含封闭在内部的空间,但表面积不包含在外面看不到的面。

思路

假想是从一个大的立方体中抠出这个雕塑,通过BFS计算多余体积,再从立方体中抠掉即可。同时,表面积也可以计算出来。
题目坐标系比较大,需要离散化。一开始有一点没想明白,怎么处理相邻两个长方体是否连接起来。实际上,只需要在描述长方体的长宽高区间时,采用左开右闭的方法处理即可。

链接

https://vjudge.net/problem/UVA-12171

代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

const int maxx = 1010;
const int maxn = 100+10;

struct node{
    int x, y, z;
    node(){}
    node(int x,int y, int z):x(x), y(y), z(z){}
    void read(){scanf("%d %d %d", &x, &y, &z);}
    node operator +(node a){
        return node(x + a.x, y + a.y, z + a.z);
    }
    void show(){
        printf("%d %d %d\n", x, y, z);
    }
};

node mov[6];
int T, n;
node P[maxn];
vector<int> X, Y, Z;
bool G[maxn][maxn][maxn];
bool vis[maxn][maxn][maxn];

void push_in(node &a){
    X.push_back(a.x);
    Y.push_back(a.y);
    Z.push_back(a.z);
}

void compress(vector<int> &a){
    a.push_back(0);
    a.push_back(maxx);
    sort(a.begin(), a.end());
    a.erase(unique(a.begin(), a.end()), a.end());
}

int get_id(int d, vector<int> &D){
    return lower_bound(D.begin(), D.end(), d) - D.begin();
}

int get_area(node &d, int dir){
    if(mov[dir].z != 0)
        return (X[d.x+1] - X[d.x]) * (Y[d.y+1] - Y[d.y]);
    else if(mov[dir].y != 0)
        return (X[d.x+1] - X[d.x]) * (Z[d.z+1] - Z[d.z]);
    return (Y[d.y+1] - Y[d.y]) * (Z[d.z+1] - Z[d.z]);
}

int main(){
    mov[0] = node(1, 0, 0);
    mov[1] = node(-1, 0, 0);
    mov[2] = node(0, 1, 0);
    mov[3] = node(0, -1, 0);
    mov[4] = node(0, 0, 1);
    mov[5] = node(0, 0, -1);

    scanf("%d", &T);
    while(T--){
        int v = 0, s = 0;
        X.clear();Y.clear();Z.clear();
        memset(vis, false, sizeof vis);
        memset(G, false, sizeof G);

        scanf("%d", &n);
        for(int i = 0; i < (n<<1); i+=2){
            P[i].read();
            P[i+1].read();
            P[i+1] = P[i] + P[i+1];
            push_in(P[i]);
            push_in(P[i+1]);
        }

        compress(X);
        compress(Y);
        compress(Z);

        //构造离散化的小图
        for(int i = 0; i < (n<<1); i += 2){
            int x0 = get_id(P[i].x, X), x1 = get_id(P[i+1].x, X);
            int y0 = get_id(P[i].y, Y), y1 = get_id(P[i+1].y, Y);
            int z0 = get_id(P[i].z, Z), z1 = get_id(P[i+1].z, Z);

            for(int x = x0; x < x1; ++x){
                for(int y = y0; y < y1; ++y){
                    for(int z = z0; z < z1; ++z){
                        G[x][y][z] = true;
                    }
                }
            }
        }

        queue<node> qu;
        qu.push(node(0, 0, 0));
        vis[0][0][0] = true;

        while(!qu.empty()){
            node t = qu.front();
            qu.pop();

            if(!G[t.x][t.y][t.z]){
                v += (X[t.x+1] - X[t.x]) * (Y[t.y+1] - Y[t.y]) * (Z[t.z+1] - Z[t.z]);
            }

            for(int i = 0; i < 6; ++i){
                node mt = t + mov[i];

                if(mt.x < 0 || mt.x >= X.size()-1 || mt.y < 0 || mt.y >= Y.size()-1 || mt.z < 0 || mt.z >= Z.size()-1)
                    continue;
                if(G[mt.x][mt.y][mt.z]){
                    s += get_area(mt, i);
                }else if(!vis[mt.x][mt.y][mt.z]){
                    qu.push(mt);
                    vis[mt.x][mt.y][mt.z] = true;
                }
            }
        }

        printf("%d %d\n", s, maxx * maxx * maxx - v);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值