12171 - Sculpture (UVA)

题目链接如下:

Online Judge

这道题我开始的解法是很笨拙的,小数据上结果是对的,但OJ上提交一直显示编译错误,到现在我还不知道错在哪……后来参考了 hdu 2771(uva 12171) Sculpture bfs+离散化-CSDN博客 这里的解法,这个解法应该是参考了刘汝佳的解法。离散化对我来说是比较陌生的概念,还学习了一下unique的用法(sort之后unique,指向不重复的数据的下一个位置)。

我最后的代码如下:

#include <cstdio>
#include <algorithm>
#include <deque>
#include <vector>
const int maxx = 1005;
// #define debug

struct node{
    int x, y, z;
    node(int _x, int _y, int _z): x(_x), y(_y), z(_z){}
};
struct box{
    int x0, y0, z0, x, y, z;
    box(int _x0, int _y0, int _z0, int _x, int _y, int _z): x0(_x0), y0(_y0), z0(_z0), x(_x), y(_y), z(_z){}
};
int T, n, x0, y0, z0, x, y, z, nx, ny, nz, area, vol, totVol;
int cube[101][101][101];
int dx[] = {-1, 1, 0, 0, 0, 0};
int dy[] = {0, 0, 1, -1, 0, 0};
int dz[] = {0, 0, 0, 0, 1, -1};
std::vector<box> boxVec;
std::vector<int> xVec, yVec, zVec;

void reset(){
    for (int i = 0; i < 101; ++i){
        for (int j = 0; j < 101; ++j){
            for (int k = 0; k < 101; ++k){
                cube[i][j][k] = 0;
            }
        }
    }
}

void discretize(std::vector<int> &vec, int &n){
    sort(vec.begin(), vec.end());
    n = std::unique(vec.begin(), vec.end()) - vec.begin();
}

int id(std::vector<int> &vec, int k){
    return find(vec.begin(), vec.end(), k) - vec.begin();
}

void floodfill(int i, int j, int k){
    std::deque<node> dq;
    cube[i][j][k] = -1;
    dq.push_back(node(i, j, k));
    while (!dq.empty()){
        node temp = dq.front();
        dq.pop_front();
        i = temp.x;
        j = temp.y;
        k = temp.z;
        vol += (xVec[i + 1] - xVec[i]) * (yVec[j + 1] - yVec[j]) * (zVec[k + 1] - zVec[k]);
        for (int u = 0; u < 6; ++u){
            if (i + dx[u] >= 0 && i + dx[u] <= 100 && j + dy[u] >= 0 && j + dy[u] <= 100 && k + dz[u] >= 0 && k + dz[u] <= 100 && cube[i + dx[u]][j + dy[u]][k + dz[u]] == 1){
                if (dx[u]){
                    area += (yVec[j + 1] - yVec[j]) * (zVec[k + 1] - zVec[k]);
                } else if (dy[u]){
                    area += (xVec[i + 1] - xVec[i]) * (zVec[k + 1] - zVec[k]);
                } else if (dz[u]){
                    area += (xVec[i + 1] - xVec[i]) * (yVec[j + 1] - yVec[j]);
                }
            }
        }
        for (int u = 0; u < 6; ++u){
            if (i + dx[u] >= 0 && i + dx[u] < nx - 1 && j + dy[u] >= 0 && j + dy[u] < ny - 1 && k + dz[u] >= 0 && k + dz[u] < nz - 1 && cube[i + dx[u]][j + dy[u]][k + dz[u]] == 0){
                cube[i + dx[u]][j + dy[u]][k + dz[u]] = -1;
                dq.push_back(node(i + dx[u], j + dy[u], k + dz[u]));
            }
        }
    }
}

int main(){
    #ifdef debug
    freopen("0.txt", "r", stdin);
    freopen("1.txt", "w", stdout);
    #endif
    scanf("%d", &T);
    totVol = maxx * maxx * maxx;
    while (T--){
        scanf("%d", &n);
        if (n == 0){
            printf("0 0\n");
            continue;
        }
        boxVec.clear();
        xVec.clear();
        yVec.clear();
        zVec.clear();
        xVec.push_back(0);
        xVec.push_back(maxx);
        yVec.push_back(0);
        yVec.push_back(maxx);
        zVec.push_back(0);
        zVec.push_back(maxx);
        area = vol = 0;
        for (int l = 0; l < n; ++l){
            scanf("%d %d %d %d %d %d", &x0, &y0, &z0, &x, &y, &z);
            boxVec.push_back(box(x0, y0, z0, x0 + x, y0 + y, z0 + z));
            xVec.push_back(x0);
            xVec.push_back(x0 + x);
            yVec.push_back(y0);
            yVec.push_back(y0 + y);
            zVec.push_back(z0);
            zVec.push_back(z0 + z);
        }
        discretize(xVec, nx);
        discretize(yVec, ny);
        discretize(zVec, nz);
        for (int l = 0; l < n; ++l){
            for (int i = id(xVec, boxVec[l].x0); i < id(xVec, boxVec[l].x); ++i){
                for (int j = id(yVec, boxVec[l].y0); j < id(yVec, boxVec[l].y); ++j){
                    for (int k = id(zVec, boxVec[l].z0); k < id(zVec, boxVec[l].z); ++k){
                        cube[i][j][k] = 1;
                    }
                }
            }
        }
        floodfill(0, 0, 0);
        printf("%d %d\n", area, totVol - vol);
        reset();
    }
    #ifdef debug
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
}

我原先的解法如下(oj上有编译错误....小数据没错):

#include <cstdio>
#include <algorithm>
#include <deque>
const int maxx = 1005;
// #define debug

struct node{
    int x, y, z;
    node(int _x, int _y, int _z): x(_x), y(_y), z(_z){}
};
int T, n, x0, y0, z0, x, y, z, minX, minY, minZ, maxX, maxY, maxZ, area, vol;
int cube[maxx][maxx][maxx];
int dx[] = {-1, 1, 0, 0, 0, 0};
int dy[] = {0, 0, 1, -1, 0, 0};
int dz[] = {0, 0, 0, 0, 1, -1};

void reset(){
    for (int i = minX; i <= maxX; ++i){
        for (int j = minY; j <= maxY; ++j){
            for (int k = minZ; k <= maxZ; ++k){
                cube[i][j][k] = 0;
            }
        }
    }
}

int main(){
    #ifdef debug
    freopen("0.txt", "r", stdin);
    freopen("1.txt", "w", stdout);
    #endif
    scanf("%d", &T);
    while (T--){
        scanf("%d", &n);
        if (n == 0){
            printf("0 0\n");
            continue;
        }
        minX = minY = minZ = maxx - 1;
        maxX = maxY = maxZ = 0;
        area = vol = 0;
        for (int l = 0; l < n; ++l){
            scanf("%d %d %d %d %d %d", &x0, &y0, &z0, &x, &y, &z);
            minX = std::min(minX, x0 - 1);
            minY = std::min(minY, y0 - 1);
            minZ = std::min(minZ, z0 - 1);
            maxX = std::max(maxX, x0 + x + 1);
            maxY = std::max(maxY, y0 + y + 1);
            maxZ = std::max(maxZ, z0 + z + 1);
            for (int i = x0; i < x0 + x; ++i){
                for (int j = y0; j < y0 + y; ++j){
                    for (int k = z0; k < z0 + z; ++k){
                        cube[i][j][k] = 1;
                    }
                }
            }
        }
        std::deque<node> dq;
        cube[minX][minY][minZ] = -1;
        dq.push_back(node(minX, minY, minZ));
        while (!dq.empty()){
            node temp = dq.front();
            dq.pop_front();
            for (int u = 0; u < 6; ++u){
                int xx = temp.x + dx[u];
                int yy = temp.y + dy[u];
                int zz = temp.z + dz[u];
                if (xx >= minX && xx <= maxX && yy >= minY && yy <= maxY && zz >= minZ && zz <= maxZ && !cube[xx][yy][zz]){
                    cube[xx][yy][zz] = -1;
                    dq.push_back(node(xx, yy, zz));
                }
            }
        }
        for (int i = minX; i <= maxX; ++i){
            for (int j = minY; j <= maxY; ++j){
                for (int k = minZ; k <= maxZ; ++k){
                    if (!cube[i][j][k]){
                        cube[i][j][k] = 1;
                    }
                    if (cube[i][j][k] == 1){
                        vol++;
                    }
                }
            }
        }
        for (int i = minX; i <= maxX; ++i){
            for (int j = minY; j <= maxY; ++j){
                for (int k = minZ; k <= maxZ; ++k){
                    if (cube[i][j][k] == 1){
                        if (i - 1 >= minX && cube[i - 1][j][k] == -1){
                            area++;
                        }
                        if (j - 1 >= minY && cube[i][j - 1][k] == -1){
                            area++;
                        }
                        if (k - 1 >= minZ && cube[i][j][k - 1] == -1){
                            area++;
                        }
                        if (i + 1 <= maxX && cube[i + 1][j][k] == -1){
                            area++;
                        }
                        if (j + 1 <= maxY && cube[i][j + 1][k] == -1){
                            area++;
                        }
                        if (k + 1 <= maxZ && cube[i][j][k + 1] == -1){
                            area++;
                        }
                    }
                }
            }
        }
        printf("%d %d\n", area, vol);
        reset();
    }
    #ifdef debug
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值