hiho151周*

题目链接

题目大意:依次在给定的三维坐标上垒方块,对于一个新的坐标需满足两个条件

1:六个方向有相邻的方块或者z==1【题目说明了初始状态是:所有z==0的位置都有方块】

2:该位置存在一条到无穷远处的路径,即不能被已有的方块包围。

给定一个序列,问按照这个序列放置方块会不会违反上述两条规则。

1<=x,y,z<=100  N<=100000

-----------------------------------------------------------------------------------------------------

条件一容易判断。

条件二如果正序处理,则每来一个坐标都需要判断和无穷远处的连通性,复杂度很大。

则反过来处理,首先把空格子合并,分到几个集合里。然后倒着删方块,每删一个方块,就merge一下该

方块及周围的六个空格子,merge完后判断方块所在格子是否和无穷远处联通

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

#define MAX(a,b) ((a)>=(b)?(a):(b))
#define MIN(a,b) ((a)<=(b)?(a):(b))
#define OO 0x0fffffff
using namespace std;
const int N = 128;
bool tag[N][N][N];
int father[N*N*N];
int ids[N][N][N];
int xs[100100],ys[100100],zs[100100];
int maxx,maxy,maxz;
int minx,miny,minz;
const int dir[6][3] = {{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}};
bool judge(int x,int y,int z){
    if(z==0) return false;
    if(x<minx) return false;
    if(x>maxx) return false;
    if(y<miny) return false;
    if(y>maxy) return false;
    if(z<minz) return false;
    if(z>maxz) return false;
    return true;
}
int find(int id){
    int fid = father[id];
    if(fid==id) return fid;
    return (father[id]=find(fid));
}
void merge(int a,int b){
    int fa = find(a);
    int fb = find(b);
    if(fa==fb) return ;
    father[fb] = fa;
}

int main(){
    int n,t;
    for(int i=0;i<103;i++) for(int j=0;j<103;j++) for(int k=0;k<103;k++){
        ids[i][j][k] = i*10404+j*102+k;
    }
    for(scanf("%d",&t);t--;){
        cin>>n;
        memset(tag,false,sizeof(tag));
        bool flag = true;
        maxx=maxy=maxz=-OO;
        minx=miny=minz=OO;
        for(int i=0;i<n;i++){
            scanf("%d%d%d",xs+i,ys+i,zs+i);
            maxx=MAX(maxx,xs[i]);maxy=MAX(maxy,ys[i]);maxz=MAX(maxz,zs[i]);
            minx=MIN(minx,xs[i]);miny=MIN(miny,ys[i]);minz=MIN(minz,zs[i]);

            if(tag[xs[i]][ys[i]][zs[i]]) flag = false;
            else if(zs[i]==1){
                tag[xs[i]][ys[i]][zs[i]] = true;
            }
            else{
                for(int d=0;d<6;d++){
                    int tx = xs[i]+dir[d][0];
                    int ty = ys[i]+dir[d][1];
                    int tz = zs[i]+dir[d][2];
                    if(tag[tx][ty][tz]){
                        tag[xs[i]][ys[i]][zs[i]] = true;
                        break;
                    }
                }
                if(!tag[xs[i]][ys[i]][zs[i]]) flag = false;
            }
        }
        if(!flag) puts("No");
        else{
            minx--;miny--;minz--;
            maxx++;maxy++;maxz++;
            for(int id=ids[minx][miny][minz];id<=ids[maxx][maxy][maxz];id++) father[id] = id;
            for(int i=minx;i<=maxx;i++)
            for(int j=miny;j<=maxy;j++)
            for(int k=minz;k<=maxz;k++){
                if((k!=0)&&(!tag[i][j][k])){
                    for(int d=0;d<6;d++){
                        int ti = i+dir[d][0];
                        int tj = j+dir[d][1];
                        int tk = k+dir[d][2];
                        if(judge(ti,tj,tk)&&(!tag[ti][tj][tk])){
                            merge(ids[i][j][k],ids[ti][tj][tk]);
                        }
                    }
                }
            }

            int ancestor = ids[maxx][maxy][maxz];
            for(int i=n-1;i>=0;i--){
                if(!flag) break;
                int curId = ids[xs[i]][ys[i]][zs[i]];
                for(int d=0;d<6;d++){
                     int tx = xs[i]+dir[d][0];
                     int ty = ys[i]+dir[d][1];
                     int tz = zs[i]+dir[d][2];
                     if(judge(tx,ty,tz)&&(!tag[tx][ty][tz])){
                        merge(curId,ids[tx][ty][tz]);
                     }
                }
                if(find(curId)!=find(ancestor)){
                    flag = false;
                }
                else{
                    tag[xs[i]][ys[i]][zs[i]]=false;
                }
            }
            if(!flag) puts("No");
            else puts("Yes");
        }
    }
    return 0;
}
时间: 2024-10-08 17:16:24

hiho151周*的相关文章

win10周年版eNSP中启动AR提示错误代码40问题

win 10操作系统中安装eNSP 1.2.00.380,一直运行正常,但在2016年11月升级win 周年版之后,启动AR时启动失败,提示错误代码40. 卸载eNSP及VirtualBox之后重装问题依旧.按照论坛和网上各种说法更新virtualbox修改虚拟网卡设置,或者重新注册都无法解决,最终多方查找终于找到解决方案. 环境:win10 周年版,eNSP 1.2.00.380,VirtualBox 4.2.8 eNSP注册后virtualbox管理器中会出现AR_Base,WLAN_AC_

每周进度条(第十五周)

第十五周进度条   第十五周 所花时间 1h 代码量(行)  100 博客量(篇)  1 学到的知识 对图片的处理 在Android程序中加入图片

201405644 嵌入式程序设计第五周学习总结

嵌入式课程设计第五周学习总结 标准 I/O 编程 标准 I/O 提供流缓冲的目的是尽可能减少使用 read()和 write()等系统调用的数量.标准 I/O 提供了 3 种类型 的缓冲存储.全缓冲.行缓冲.不带缓冲. 打开文件 打开文件有三个标准函数,分别为:fopen().fdopen()和 freopen().其中 fopen()可以指定打开文件的路径和模式,fdopen()可以指定打开的文件描述符和模式,而 freopen() 除可指定打开的文件.模式外,还可指定特定的 I/O 流. f

20155208徐子涵 2016-2017-2 《Java程序设计》第6周学习总结

20155208徐子涵 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 10.1.1 1.Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串流对象. 2.若要将数据从来源中取出,可以使用输入串流:若要将数据写入目的地,可以使用输出串流.在java中,输入串流代表对象为java.in.InputStream的实例:输出串流代表对象为java.io.Outputstream的实例. 3.read()方法每次尝试读取数据,并返回实际读入的,只要不是负一

20155336 2016-2017-2《JAVA程序设计》第一周学习总结

# 20155336  2016-2017-2<JAVA程序设计>第1周学习总结 ## 教材学习内容总结 开学的第一周,带着些许的欣喜和好奇,听完了老师的第一堂课.说心里话学习JAVA仿佛观看一部英文影视作品一样头疼, 因为总会有许许多多相似的名字让你记得晕头转向.JAVA也是一样,什么JVM啊JRE啊JDK啊 (/(ㄒoㄒ)/~~)  等等一系列 的英文缩写,让人心神意乱~~但总体上对JAVA有了一个初步的了解.通过课上老师的介绍以及课下对JAVA书第一章的浏览, 我简单的了解了JAVA艰辛

《七周七数据库》读书分享

# 七周七数据库 读书分享会第一期 2017.02.12 <七周七数据库> - Eric Redmond ## 预备知识 ACID:原子 一致 隔离 持久 CAP原则:一致性 可用性 分区容错性,在分布式环境下,至多只能同时满足其二 "小明,你的数据库作业呢?""我可以今天提交一半的作业,或者明天提交全部的作业,但无法在今天提交全部的作业.""...小明你给我滚出去!" 小知识点: * 原子性:原子性代表中间状态的透明性,想象从a账户

20145336张子扬 《信息安全系统设计基础》第7周学习总结

20145336张子扬 <信息安全系统设计基础>第1周学习总结 教材学习内容总结 学习目标: 了解常见的存储技术(RAM.ROM.磁盘.固态硬盘等) 理解局部性原理 理解缓存思想 理解局部性原理和缓存思想在存储层次结构中的应用 高速缓存的原理和应用 三种常见存储技术:RAM.ROM和磁盘 随机访问存储器RAM分为静态RAM(SRAM)和动态RAM(DRAM) SRAM 用来作为高速缓存储存器,SRAM将每个位存储在一个双稳态的存储器单元里,每个单元是用一个六晶体管电路来实现的.它可以无限制地保

20145317《信息安全系统设计基础》第六周学习总结(1)

20145317<信息安全系统设计基础>第六周学习总结(1) 第四章 处理器体系结构 指令体系结构:一个处理器支持的指令和指令的字节级编码 4.1Y86指令集体系结构 Y86:包括定义各种状态元素.指令集和它们的编码.一组编程规范和异常事件处理. Y86程序中的每条指令都会读取或修改处理器状态的某些部分.Y86具体包括:8个程序寄存器.3个条件码ZF\SF\OF.程序计数器(PC) Y86用虚拟地址引用存储器位置. 程序状态的最后一个部分是状态码Stat,它表明程序执行的总体状态. 注意:条件

20145239 《信息安全系统设计基础》第5周学习总结

20145239<信息安全系统设计基础>第5周学习总结 教材学习内容 x86寻址方式 DOS时代的平坦模式,不区分用户空间和内核空间,很不安全 8086的分段模式 IA32的带保护模式的平坦模式 机器级编程的两种抽象 -ISA(Instruction set architecture).ISA简单来说就是指令集体系结构.定义了处理机状态,指令格式以及指令对状态的影响.-机器级使用的存储器地址是虚拟地址. 机器代码中的处理机状态 程序计数器(PC)表示将要执行的下一条指令在存储器中的地址. 整数