奶酪——并查集,BFS,DFS(NOIP2017提高组)

news2024/11/16 9:23:47

目录

题目

思路

并查集

代码(java)

BFS(DFS同理)

代码(C++)


题目

思路

        这个题目意思是有很多个球分布在一个三维空间内,如果这些球相切或者相交都可以互相到达,我们需要判断能否通过这些球从底部到达顶部。可以抽象为,所有的球构成了一个图,球即是图中的点,相切或者相交说明两点之间有线。因此我们可以想到,将所有的点组成一个集合,只需要判断这个集合能否到达底部和顶部。

        因此可以使用并查集来组成集合。

        最主要的是这个题n只有1000,因此暴力做也没问题。

并查集

        我们判断每两个球,是否相交或者相切,将所有相切或者相交的球装入到一个集合中去,最后判断是否到达高度为0和n。

        构成集合后,如何判断是否到达 0 和 h?我们可以事先在读入球心数据的时候,判断该球是否与 z = 0 相切或者相交,同样判断是否与 z = h 相切或者相交。

        我这里用 0 表示与第 0 层相交,n+1 表示与第 h 层相交。(因为使用数组下标来表示该球,因此用 n+1 来表示n个球之外的,表示到达h)。

        如果与 0 相交,则 find(i) = 0;与h相交,则 find(i)=n+1;

        最后如果 find(0) == find(n+1) ,则说明可以到达。

        因为需要遍历每两个球,所以时间复杂度是O(n^2)

代码(java)

        注意只有一个球的时候 

import java.io.*;
import java.util.*;

class Main{
    static int N = 1010;
    static int T;
    static int n,h,r;
    static int[] p = new int[N];
    static int[] x = new int[N];
    static int[] y = new int[N];
    static int[] z = new int[N];
    static boolean[] st = new boolean[N];
    public static void main(String[] args) throws IOException{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        T = Integer.parseInt(in.readLine().split(" ")[0]);
        while(T-->0){
            String[] s = in.readLine().split(" ");
            n = Integer.parseInt(s[0]);
            h = Integer.parseInt(s[1]);
            r = Integer.parseInt(s[2]);
            // 初始化p[]
            for(int i=0;i<=n+1;i++)
                p[i] = i;
            // 读取
            for(int i=1;i<=n;i++){
                s = in.readLine().split(" ");
                x[i] = Integer.parseInt(s[0]);
                y[i] = Integer.parseInt(s[1]);
                z[i] = Integer.parseInt(s[2]);
                if(z[i]+r>=h) p[i] = find(n+1); // 如果连接顶部,将他加到n+1集合
                if(z[i]-r<=0) { // 如果连接底部,其中也同样连接顶部,则直接令find(0)==find(n+1),否则,加到0集合
                    if(p[i]!=i) p[find(0)] = find(n+1);
                    else p[i] = find(0);
                }
            }
            // 构成并查集
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(get(x[i],x[j],y[i],y[j],z[i],z[j])<=4.0*r*r){
                        int pi = find(i);
                        int pj = find(j);
                        if(pi!=pj){
                            p[pi] = pj;
                        }
                    }
                }
            }
            if(find(0)==find(n+1)) System.out.println("Yes");
            else System.out.println("No");
        }
    }
    // 找根节点
    public static int find(int u){
        if(p[u]!=u) p[u] = find(p[u]);
        return p[u];
    }
    // 计算两个圆的路径长度
    public static double get(int x1,int x2,int y1,int y2,int z1,int z2){
         return Math.pow(x1-x2,2)+Math.pow(y1-y2,2)+Math.pow(z1-z2,2);
    }
}

BFS(DFS同理)

        我们可以不事先将所有的球都装入到一个集合,我们直接从最底部的球进行判断,使用bfs向上进行扩展,如果扩展到某个球到达h,说明可以到达。

        相当于是一个多源bfs问题,因为与0相交或者相切的球可能有多个。

        每个球都只需要遍历一遍,但遍历到每个球的时候都需要遍历一遍所有的球,找出其中与当前球相切或者相交的球,然后进行bfs。

        因为每遍历到一个球都需要遍历所有的球,因此时间复杂度也是O(n^2),但是比并查集快,因为如果中途遍历到可以到达 h,则不用再遍历,而并查集要遍历所有的点。

代码(C++)

作者:Conan15
链接:https://www.acwing.com/solution/content/99009/ 

#include <bits/stdc++.h>
using namespace std;
int t, n, h, r, f[1010];
double x[1010], y[1010], z[1010];
inline double dist(double X1, double X2, double Y1, double Y2, double Z1, double Z2) {
    return sqrt((X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2) + (Z1 - Z2) * (Z1 - Z2));
}

int main() {
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d%d", &n, &h, &r);
        for (int i = 1; i <= n; i++) scanf("%lf%lf%lf", &x[i], &y[i], &z[i]), f[i] = 0;
        queue<int> q; bool ok = 0;
        for (int i = 1; i <= n; i++) 
            if (z[i] <= r) q.push(i), f[i] = 1;
        while (q.size()) {
            int p = q.front(); q.pop();
            if (ok) break;
            if (z[p] + r >= h) {ok = 1; puts("Yes"); break;}
            for (int i = 1; i <= n; i++) {
                if (f[i]) continue;
                if (dist(x[p], x[i], y[p], y[i], z[p], z[i]) <= 2 * r) {
                    q.push(i), f[i] = 1;
                    if (z[i] + r >= h) {ok = 1; puts("Yes"); break;}
                }
            }
        }
        if (!ok) puts("No");
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1605820.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【python从入门到精通】-- 第五战:函数大总结

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文…

元宇宙VR虚拟线上展馆满足企业快速布展的需要

想要拥有一个VR线上虚拟展馆&#xff0c;展现您的城市风采或企业特色吗? 相比实体展馆搭建&#xff0c;VR线上虚拟展馆投入资金少&#xff0c;回报周期短&#xff0c;只需几个月的时间&#xff0c;您就能开始资金回笼。那么一个VR线上虚拟展馆多少钱呢? 深圳VR公司华锐视点基…

C语言如何使⽤指针?

一、问题 指针变量在初始化以后就可以使⽤和参与操作了&#xff0c;那么就要⽤到对指针变量最常⽤的两个操作符——> * 和 &#xff06; 。 二、解答 这⾥⼜要提到始终贯穿着指针的⼀个符号“ * ”&#xff0c;但是这⾥的“ * ”是作为指针运算符使⽤的&#xff0c;叫做取内…

三大常用自动化框架对比

上次发布过性能测试工具的对比后&#xff0c;有小伙伴后台留言&#xff0c;想了解一下自动化测试框架的对比&#xff0c;尤其是RobotFramework、pytest和unitest之间的优劣势情况。 这不我们今天就来分析一下他们之间的区别和各自的优缺点。 1 RobotFramework 优点&#xff1a;…

selenium 下载文件取消安全下载的方法

问题描述 我要从一个网站上下载文件&#xff0c;谷歌浏览器总是自动阻止下载&#xff0c;并询问我是否保留。 可是&#xff0c;我想要的是不要询问&#xff0c;默认下载即可。 运行环境 OS: macOSselenium: 4.19.0python: 3.10.11Chrome: 124.0.6367.62selenium chromedrive…

openEuler-23.03下载

下载地址&#xff1a;openEuler下载 | 欧拉系统ISO镜像 | openEuler社区官网 下载版本&#xff1a;openEuler-23.03-x86_64-dvd.iso

CTF中常见的四种python逆向

说在前面&#xff1a; 什么是pyc文件&#xff1f; pyc是一种二进制文件&#xff0c;是由py文件经过编译后&#xff0c;生成的文件&#xff0c;是一种byte code&#xff0c;py文件变成pyc文件后&#xff0c;加载的速度有所提高&#xff0c; pyc 文件是 Python 编译过的字节码文…

WdatePicker异常,无法弹出日期选择框

官网&#xff1a;My97日期控件官方网站 My97 DatePickerhttp://www.my97.net/ 可能使版本太老了&#xff0c;可以更新一下&#xff0c;然后根据官方的文件进行使用。 我的异常是因为在网上找的包里面缺少文件&#xff0c;去官网拉了一下最新的就行了。

【Linux驱动层】iTOP-RK3568学习之路(二):vscode中设置头文件路径-完成代码自动补全

在Ubuntu下用vscode写Linux驱动层的时候&#xff0c;需要添加头文件&#xff1a; #include<linux/module.h> #include<linux/init.h> #include<linux/kernel.h>但vscode没有智能提示&#xff0c;因此需要我们手动添加自己的头文件路径&#xff1a; topeetu…

Ubuntu 23.10.1 nginx源码安装

注&#xff1a;以下所有命令均在root管理员模式下&#xff0c;若不是&#xff0c;请在所有命令前加sudo 1、安装依赖库 1.1、安装gcc g的依赖库 apt-get install build-essential apt-get install libtool1.2、安装pcre依赖库 apt-get update apt-get install libpcre3 lib…

嵌入式科普(15)小米su7成本分析和拆解之智驶、座舱分析

目录 一、概述 二、小米su7成本分析 2.1 整车成本构成 2.2 三电系统 2.3 车身与底盘 2.3 智能网联 2.4 内外饰 三、小米su7拆解之智驶、座舱分析 3.1 主要芯片 3.2 智能驾驶&智能座舱 四、NXP S32K324汽车通用微控制器 嵌入式科普(15)小米su7成本分析和拆解之智…

【结构型模式】外观模式

​一、外观模式概述 外观模式定义与意图&#xff1a;外观类为复杂的子系统提供了一个统一的入口。外观模式定义了一个高层接口&#xff0c;这个接口使得这一子系统更加容易使用。&#xff08;对象结构型模式&#xff09; 外观模式的特点&#xff1a; 1.又叫做门面模式&#xf…

JRT在线初始化完善

之前实现的在线初始化留了个尾巴&#xff0c;那就是环境下载页构造zip包的时候没修改JRTBrowser的连接串地址为当前网站&#xff0c;这样就要求网站部署好之后给用户下载之前有人要把服务器的浏览器地址配置好。这样就增加一个运维工作&#xff0c;如果忘了或者不知道的人就会导…

在Windows安装R语言

直接安装R语言软件 下载网址&#xff1a;R: The R Project for Statistical Computing 下载点击install R for the first time 通过Anaconda下载RStudio 提前下载好Anaconda 点击Anaconda Navigate 点击RStudio的Install下载就好了

labelimg安装和使用(解决闪退问题)

&#x1f308;个人主页&#xff1a;Rookie Maker &#x1f525; 系列专栏&#xff1a;计算机视觉 &#x1f3c6;&#x1f3c6;关注博主&#xff0c;随时获取更多关于IT的优质内容&#xff01;&#x1f3c6;&#x1f3c6; &#x1f600;欢迎来到我的代码世界~ &#x1f601; 喜…

【行为型模式】命令模式

一、命令模式概述 命令模式的定义&#xff1a;将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。(对象行为型) 命令模式优缺点&#xff1a; 优点&#xff1a; 1.类间解耦&#xff1a;调用者角色与接收者角色之间没有任何依…

复合升降机器人教学科研平台——技术方案

一&#xff1a;功能概述 1.1 功能简介 复合升降机器人是一款集成移动底盘、机械臂、末端执行器、边缘计算平台等机构形成的教学科研平台&#xff0c;可实现机器人建图导航、路径规划&#xff0c;机械臂运动学、动力学、轨迹规划、视觉识别等算法功能和应用&#xff0c;提供例如…

Kubernetes 容器网络技术架构及原理分析,赋能数字化转型

浅谈容器网络原理 我们将深入探讨容器和 Kubernetes 的网络原理,以全面了解 Kubernetes Network 的 Service。这些知识将帮助您轻松理解和使用 Service。 容器技术充分利用 Linux 的原生功能,如命名空间隔离、cgroup 限制和 rootfs,实现隔离和限制。同样地,容器网络也依赖…

改手机IP地址的软件推荐

随着移动互联网的普及&#xff0c;手机已成为人们日常生活中不可或缺的一部分。而在使用手机的过程中&#xff0c;IP地址作为一个重要的网络标识&#xff0c;有时也需要进行修改或更改。为了满足这一需求&#xff0c;市面上涌现出了许多改手机IP地址的软件。虎观代理将对这些软…

202462读书笔记|《一世珍藏的诗歌200首》——你曾经羞赧地向我问起, 是谁最早在此留下足印

202462读书笔记|《一世珍藏的诗歌200首》——你曾经羞赧地向我问起&#xff0c; 是谁最早在此留下足印 《一世珍藏的诗歌200首》作者金宏宇&#xff0c;很多美好的诗&#xff0c;有徐志摩&#xff0c;戴望舒&#xff0c;林徽因&#xff0c;舒婷等的诗精选&#xff0c;很值得一读…