题目链接


人生第一篇题解,多多关照吧。



##注意事项:
1.多组数据,每次要*先初始化*。
2.因为涉及到开根,所以记得*开double*。
##整体思路:
建图,判断「起点」与「终点」是否连通。
方法可选择搜索(我写的BFS)或并查集(UFS)。
首先,读入时记录这些球的最小高度和最大高度,如果最低的球与底面相离,或是最高的球与顶面相离,直接Pass。
我们会发现,可能不止一个球与底面相切或相交,也可能不止一个球与顶面相切或相交。
这就是说,起点和终点都可能不止一个,这给我们操作造成了一些麻烦(然而考场上我就这么硬搜的居然AC了)。
其实,通过建立**「超级起点」**和**「超级终点」**,可以把操作变得简单——用结构体数组的第0个元素表示「超级起点」,第n+1个元素表示「超级终点」。
##两种方法都需要进行的预处理操作:
对于每一组球(i,j),计算两球球心距离是否小于半径×2。
走一遍所有的球,如果当前球可以做起点,就连上当前球和超级起点;终点亦然。
###方法1——BFS:
用二维bool数组e[i][j]记录i能否到达j,相当于存图(链式前向星也可以的,只是本题数据范围没有必要)。
对于每一个球,依次判断其能否到达0..n+1,当「超级终点」已被访问或队列已为空时结束搜索。
如果「超级终点」被访问过说明搜到了,可以到达;否则无法到达。

```cpp
#include
#include
#include
#include
#include
using namespace std;
const int MAXN=1010;
bool vis[MAXN],e[MAXN][MAXN];
double h,r,low,high;
int T,n;
struct ball
{
double x,y,z;
}s[MAXN];
double dis(ball a,ball b)
{
double t1=a.x-b.x,t2=a.y-b.y,t3=a.z-b.z;
return sqrt(t1*t1+t2*t2+t3*t3);
}
void Init()//一定记得初始化
{
low=h,high=0;
memset(vis,0,sizeof vis);
memset(e,0,sizeof e);
}
void Pre()//预处理
{
for(int i=1;i=h)//超级终点
e[n+1][i]=e[i][n+1]=1;
}
for(int i=1;i q;
q.push(0);
vis[0]=1;
while(!vis[n+1] && !q.empty())//超级终点被搜到了,或队列已空
{
int x=q.front();
q.pop();
for(int i=0;i0 || high+r
###方法2——UFS:
预处理时,如果两个球可以相连,就合并这两个球所在的UFS。
最终判断0和n+1两个球是否属于同一UFS,是则Yes,否则No。

并查集写法的代码更新于 2018.05.27,在一次水模拟赛中,原题写炸,遂重写,以前的代码风格是什么玩意!

#include <algorithm>
#include <cmath>
#include <cstdio>
using std::max;
using std::min;
const int MAXN=1010;
double h,r;
int T,n;
struct Ball
{
double x,y,z;
void Read(void)
{
scanf("%lf %lf %lf",&x,&y,&z);
}
friend double Dist(const Ball &a,const Ball &b)
{
double x=a.x-b.x,y=a.y-b.y,z=a.z-b.z;
return sqrt(x*x+y*y+z*z);
}
bool operator <(const Ball &rhs) const
{
return z<rhs.z;
}
}s[MAXN];
class UFS
{
private:
int f[MAXN];
int Find(int x)
{
return x==f[x] ? x : f[x]=Find(f[x]);
}
void Merge(int x,int y)
{
f[Find(y)]=f[Find(x)];
}
public:
UFS(int n)
{
for(int i=0;i<=n+1;++i)
f[i]=i;
for(int i=1;i<=n;++i)
{
if(s[i].z-r<=0)
Merge(0,i);
if(s[i].z+r>=h)
Merge(i,n+1);
}
for(int i=1;i<n;++i)
for(int j=i+1;j<=n;++j)
if(Dist(s[i],s[j])<=2*r)
Merge(i,j);
}
bool Connected(int x,int y)
{
return Find(x)==Find(y);
}
};
int main(int argc,char** argv)
{
scanf("%d",&T);
while(T--)
{
scanf("%d %lf %lf",&n,&h,&r);
double low=h,high=0;
for(int i=1;i<=n;++i)
{
s[i].Read();
low=min(low,s[i].z);
high=max(high,s[i].z);
}
if(low-r>0 || high+r<h)
{
puts("No");
continue;
}
UFS S(n);
puts(S.Connected(0,n+1) ? "Yes" : "No");
}
return 0;
}

/*想象一下我打完这篇文章后把文中所有的「点」一个个改成「球」*/

NOIP2017唯一AC的一道题啊。

[Luogu 3958] NOIP2017 D2T1 奶酪的更多相关文章

  1. NOIP2017 D2T1奶酪

    这题终于是正经第一题感觉了. 只需要对相交或相切的球建一条边,然后对所有与底面有交点的球连边,再对所有与顶面有交点的球连边,bfs判断上下连通性即可. #include<iostream> ...

  2. NOIP2017 D2T1 奶酪

    洛谷P3958 超级水的并没有用什么几何知识的几何题…… 直接爆搜一遍最后判断有没有与上/下表面相连的球之间连通即可……O(n2)不动脑子的复杂度 最多只是用一下并查集来判断两个点是否连通…… 具体细 ...

  3. luogu 3958 奶酪

    noip2017 D2T1 奶酪 某zz选手没有想到可以用并查集来做,直接用了dijskstra,结果被ccf老爷机卡成了70分 题目大意: 现有一块大奶酪,它的高度为 h,它的长度和宽度我们可以认为 ...

  4. [luogu P3953] [noip2017 d1t3] 逛公园

    [luogu P3953] [noip2017 d1t3] 逛公园 题目描述 策策同学特别喜欢逛公园.公园可以看成一张$N$个点$M$条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,$N ...

  5. [luogu P3960] [noip2017 d2t3] 队列

    [luogu P3960] [noip2017 d2t3] 队列 题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Syl ...

  6. [Luogu 3952] NOIP2017 时间复杂度

    [Luogu 3952] NOIP2017 时间复杂度 一年的时间说长不长,说短,也不短. 一年之内无数次觉得难得可怕的题目,原来也就模拟这么回事儿. #include <cstdio> ...

  7. 【luogu】 P1433 吃奶酪

    题目描述 房间里放着n块奶酪.一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在(0,0)点处. 输入格式: 第一行一个数n (n<=15) 接下来每行2个实数,表示第i块奶酪的坐标. ...

  8. Luogu 3959 [NOIP2017] 宝藏

    NOIP2017最后一道题 挺难想的状压dp. 受到深度的条件限制,所以一般的状态设计带有后效性,这时候考虑把深度作为一维,这样子可以保证所有状态不重复计算一遍. 神仙预处理:先处理出一个点连到一个集 ...

  9. Luogu 3960 [NOIP2017] 列队 - splay|线段树

    题解 是我从来没有做过的裂点splay... 看的时候还是很懵逼的QAQ. 把最后一列的$n$个数放在一个平衡树中, 有 $n$ 个点 剩下的$n$行数, 每行都开一个平衡树,开始时每棵树中仅有$1$ ...

随机推荐

  1. js如何处理字符串中带有↵字符

    js或vue中如何处理字符串中带有↵字符 split('\n') 使用split('\n')将字符串分割成数组就行 如果我们在vue中,只需要在页面中绑定变量时操作split('\n')就可以了: & ...

  2. Python中的list

    list的创建 1 字面量 >>>L = [1, 2, 3] [1, 2, 3] 2 通过iterable可迭代对象,比如str对象,range对象,map对象 >>&g ...

  3. Easy Summation

    Description You are encountered with a traditional problem concerning the sums of powers. Given two ...

  4. Alpha 冲刺(1/10)

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作,对多个目标检测及文字识别模型进行评估.实验,选取较 ...

  5. 《软件工程实践》第五次作业-WordCount进阶需求 (结对第二次)

    在文章开头给出结对同学的博客链接.本作业博客的链接.你所Fork的同名仓库的Github项目地址 本作业博客链接 github pair c 031602136魏璐炜博客 031602139徐明盛博客 ...

  6. Alpha-2

    前言 失心疯病源2 团队代码管理github 站立会议 队名:PMS 530雨勤(组长) 今天完成了那些任务 17:30~21:30 又测试了一些算法和代码,时间不能再拖下去了,要尽快进入代码阶段,决 ...

  7. ACM 第二天

    A - Mishka and Contest Mishka started participating in a programming contest. There are n problems i ...

  8. lintcode-15-全排列

    全排列 给定一个数字列表,返回其所有可能的排列. 注意事项 你可以假设没有重复数字. 样例 给出一个列表[1,2,3],其全排列为: [ [1,2,3], [1,3,2], [2,1,3], [2,3 ...

  9. Java中的多线程=你只要看这一篇就够了

    如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其 ...

  10. RT-thread内核之系统时钟

    一.系统时钟 rt-thread的系统时钟模块采用全局变量rt_tick作为系统时钟节拍,该变量在系统时钟中断函数中不断加1.而系统时钟中断源和中断间隔一般由MCU硬件定时器(如stm32的嘀嗒定时器 ...