出奶酪问题

题目描述:

现有一块大奶酪,它的高度为 ℎh,它的长度和宽度我们可以认为是无限大的,奶酪中间有许多 半径相同 的球形空洞。我们可以在这块奶酪中建立空间坐标系,在坐标系中,奶酪的下表面为 z=0,奶酪的上表面为 z=h。

现在,奶酪的下表面有一只小老鼠 Jerry,它知道奶酪中所有空洞的球心所在的坐标。如果两个空洞相切或是相交,则 Jerry 可以从其中一个空洞跑到另一个空洞,特别地,如果一个空洞与下表面相切或是相交,Jerry 则可以从奶酪下表面跑进空洞;如果一个空洞与上表面相切或是相交,Jerry 则可以从空洞跑到奶酪上表面。

位于奶酪下表面的 Jerry 想知道,在不破坏奶酪的情况下,最少经过多少个空洞才能够跑到奶酪的上表面去?

核心思想:看到最少/小,利用BFS

代码如下:

#include<stdio.h>
#include<math.h>
typedef struct circle {
    long long int x;
    long long int y;
    long long int z;
    int mark;//标记是否被访问过
}Circle;
typedef struct qu {
    long long int x;
    long long int y;
    long long int z;
    int d;//第几次
}Qu;
long long int dist(Qu now, Circle c)
{
    return (now.x - c.x) * (now.x - c.x) + (now.y - c.y) * (now.y - c.y) + (now.z - c.z) * (now.z - c.z);
}
//找的球应该是让高度不断增加的
int main()
{
    int T;
    scanf("%d", &T);
    for (int i = 0; i < T; i++) {
        int n;
        long long int h, r;
        scanf("%d %lld %lld", &n, &h, &r);
        Circle c[1010];
        for (int j = 0; j < n; j++) {
            scanf("%lld %lld %lld", &c[j].x, &c[j].y, &c[j].z);
            c[j].mark = 0;
        }
        Qu s;//开始的球也可以有多个
        int front, rear;
        front = rear = -1;     
        Qu q[1010]; 
        int flag1 = 1;
        for (int j = 0; j < n; j++) {
            if (c[j].z <= r) {
                s.x = c[j].x;
                s.y = c[j].y;
                s.z = c[j].z;
                s.d = 1;
                rear++;
                q[rear] = s;
                c[j].mark = 1;
                flag1 = 0;
            }
        }
        //第一个球都找不到那么就直接输出-1
        if (flag1) {
            printf("-1\n");
            continue;
        }
       
        int flag = 1;
        while (front < rear) {
            front++;
            Qu now = q[front];
            if (now.z + r >= h) {
                printf("%d\n", now.d);
                flag = 0;
                break;
            }
            //判断相切与相交
            for (int k = 0; k < n; k++) {
                if (dist(now, c[k]) <= 4*r*r&&c[k].mark==0) {
                    rear++;
                    Qu next;
                    next.x = c[k].x;
                    next.y = c[k].y;
                    next.z = c[k].z;
                    next.d = now.d + 1;
                    q[rear] = next;
                    c[k].mark = 1;
                }
            }
        }
        //BFS结束还没有找到,说明没有
        if(flag) printf("-1\n");
    }
    return 0;
}

需要注意的地方:

1.计算dist时,不要用开方,因为当输入数据过大时,sqrt传参要求时double,而输入数字又为整数,会有误差

2.因此用dist的平方<=4*r*r,但注意要用long long int类型的数据,不然数据过大会溢出

3.一开始犯的错误是找第一个球也可以有多个,当时默认只要找到一个球就可以了。

4.以前写题都是用vis多维数组记录是否被访问,但对于这个题这样做会有很大的空间浪费,一个球可以看成一个集合,因此用了代码中mark标记这种形式来判断是否访问过

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值