UVA12171 sculpture离散化思想/floodfill

z这题没有ac,但是试了无数的数据和刘汝佳的做了对比,没有看出哪里有错来

说说这题学到了什么:

第一DFS很容易栈溢出,最好使用BFS

另外在使用BFS的时候,元素一入队,就必须设置vis,否则会导致同一个元素重复入队

第二,像这种坐标类型的题目,坐标之间的关系一定要弄清楚,清除的意思是一目了然,不需要动手去计算,如果需要动手计算的话,那么编程实现起来会很困难

 

下面附上我写的代码,真心不知道哪里错了

//这道题目使用的floodfill倒是不难,难的是离散化的过程中,如何确定各个离散化后的立体块的颜色
//昨天想了半天也没有想出来
//还有一个原因是坐标和对应要涂色的块的对应关系没有搞清楚(其实这点才是主要原因)
//在color上的xyz坐标就是在对应的已经离散了的坐标里面是从第x个坐标到x+1个坐标对应的长度,而他的第x个坐标存在离散化数组的x-1个元素当中
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;

const int maxn = 100 + 10;

int x0[50 + 5],x[50 + 5],Y0[50 + 5],y[50 + 5],z0[50 + 5],z[50 + 5];
int dx[maxn],dy[maxn],dz[maxn];
int num_dx,num_dy,num_dz;

int cnt = 2;

int color[maxn][maxn][maxn];
bool is_in_cube(int x,int y,int z)
{
    if(x >= 0 && y >= 0 && z >= 0 && x < num_dx - 1 && y < num_dy - 1 && z < num_dz - 1)
        return true;
    return false;
}
int Dx[6] = {0,0,0,0,1,-1};
int Dy[6] = {1,-1,0,0,0,0};
int Dz[6] = {0,0,1,-1,0,0};

int volume = 0;
int area = 0;

int compute(int x,int y,int z,int i)
{
    if(i == 0 || i == 1)//x*y就可以了
    {
        return (dx[x + 1] - dx[x]) * (dz[z + 1] - dz[z]);
    }
    if(i == 2 || i == 3)
    {
        return (dx[x + 1] - dx[x]) * (dy[y + 1] - dy[y]);
    }
    if(i == 4 || i == 5)
    {
        return (dz[z + 1] - dz[z]) * (dy[y + 1] - dy[y]);
    }
}
struct node
{
    int x,y,z;
    node(int a = 0,int b = 0,int c = 0):x(a),y(b),z(c){}
};
//void DFS(int x,int y,int z)
//{
//    color[x][y][z] = cnt;
//    volume = volume + (dx[x + 1] - dx[x]) * (dy[y + 1] - dy[y]) * (dz[z + 1] - dz[z]);
//    for(int i_0 = 0;i_0 < 6;i_0++)
//    {
//        int X = x + Dx[i_0];
//        int Y = y + Dy[i_0];
//        int Z = z + Dz[i_0];
//        if(is_in_cube(X,Y,Z))
//        {
//            if(color[X][Y][Z] == 1)//旁边是一个涂为1的块,这个时候需要计算面积
//            {
//                area = area + compute(x,y,z,i_0);
//            }
//            if(!color[X][Y][Z])
//            {
//                DFS(X,Y,Z);
//            }
//        }
//    }
//}
int main()
{
#ifdef local
    freopen("out.txt","r",stdin);
    freopen("output2.txt","w",stdout);
#endif
    int kase;
    scanf("%d",&kase);
    for(int i_1 = 0;i_1 < kase;i_1++)
    {
        area = 0;
        volume = 0;
        memset(color,0,sizeof(color));
        memset(dx,0,sizeof(dx));
        memset(dy,0,sizeof(dy));
        memset(dz,0,sizeof(dz));
        int num_cube;
        scanf("%d",&num_cube);
        for(int i_2 = 0;i_2 < num_cube;i_2++)
        {
            scanf("%d%d%d%d%d%d",&x0[i_2],&Y0[i_2],&z0[i_2],&x[i_2],&y[i_2],&z[i_2]);
            dx[2 * i_2] = x0[i_2];
            dx[2 * i_2 + 1] = x0[i_2] + x[i_2];
            dy[2 * i_2] = Y0[i_2];
            dy[2 * i_2 + 1] = Y0[i_2] + y[i_2];
            dz[2 * i_2] = z0[i_2];
            dz[2 * i_2 + 1] = z0[i_2] + z[i_2];
        }

        dx[2 * num_cube] = 0;
        dx[2 * num_cube + 1] = 1000 + 1;
        dy[2 * num_cube] = 0;
        dy[2 * num_cube + 1] = 1000 + 1;
        dz[2 * num_cube] = 0;
        dz[2 * num_cube + 1] = 1000 + 1;//这样的话,最后一层包着的一定是空的

        sort(dx,dx + 2 * (num_cube + 1));
        sort(dy,dy + 2 * (num_cube + 1));
        sort(dz,dz + 2 * (num_cube + 1));

        num_dx = unique(dx,dx + 2 * (num_cube + 1)) - dx;//从0开始一直到505,一共有多少个坐标,但是一定少于110个
        num_dy = unique(dy,dy + 2 * (num_cube + 1)) - dy;
        num_dz = unique(dz,dz + 2 * (num_cube + 1)) - dz;

        for(int i_3 = 0; i_3 < num_cube ;i_3++)
        {
            int DX1 = lower_bound(dx,dx + num_dx,x0[i_3]) - dx ;
            int DX2 = lower_bound(dx,dx + num_dx,x0[i_3] + x[i_3]) - dx ;
            int DY1 = lower_bound(dy,dy + num_dx,Y0[i_3]) - dy ;
            int DY2 = lower_bound(dy,dy + num_dy,Y0[i_3] + y[i_3]) - dy ;
            int DZ1 = lower_bound(dz,dz + num_dz,z0[i_3]) - dz ;
            int DZ2 = lower_bound(dz,dz + num_dz,z0[i_3] + z[i_3]) - dz ;//各自是第几个坐标
            for(int j_0 = DX1;j_0 < DX2;j_0++)
            {
                for(int j_1 = DY1;j_1 < DY2;j_1++)
                {
                    for(int j_2 = DZ1; j_2 < DZ2;j_2++)
                    {
                        color[j_0][j_1][j_2] = 1;//给属于立方块的坐标块涂色
                    }
                }
            }
        }
        node fir;
        queue<node>Q;
        Q.push(fir);
        color[fir.x][fir.y][fir.z] = 2;
        while(!Q.empty())
        {
            node u = Q.front();
            Q.pop();
            //color[u.x][u.y][u.z] = 2;
            volume += (dx[u.x + 1] - dx[u.x]) * (dy[u.y + 1] - dy[u.y]) * (dz[u.z + 1] - dz[u.z]);
            for(int i = 0;i < 6;i++)
            {
                int x = u.x + Dx[i];
                int y = u.y + Dy[i];
                int z = u.z + Dz[i];
                if(is_in_cube(x,y,z))
                {
                    if(color[x][y][z] == 1)
                        area += compute(u.x,u.y,u.z,i);
                    if(!color[x][y][z])
                    {
                        node v(x,y,z);
                        color[x][y][z] = 2;//即将要入队的时候,必须要涂色,否则的话会导致重复入队
                        Q.push(v);
                    }
                }
            }
        }
        printf("%d ",area);
        printf("%d\n",dx[num_dx - 1] * dy[num_dy - 1] * dz[num_dz - 1] - volume);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/TorettoRui/p/10456109.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值