14.水晶球

题目

Description
和许多同龄女孩子一样,久莲也喜欢水晶球。
还有  天,就是心心念念的他生日了。
久莲希望把全世界最大最好看的水晶球送给他。
她找到了宝石收藏家亚瑟斯,希望能够寻求他的帮助。
亚瑟斯很快被打动了,拿出了精心收集的  块美丽的水晶石,这些水晶石初始是长宽高分别为  的长方体。亚瑟斯许诺久莲可以从中取走  块水晶石作为她礼物的原材料。
同时亚瑟斯有一种魔法,如果这两块长方形水晶石在某一个面能够完美的契合在一起(完美的契合是指这两个长方形面全等),那么可以将它们融合成一块完整的大石头,如果真的实现的话,那么久莲就可能打磨出更大的水晶球啦!
久莲太希望把最美最大的水晶球送给他了,你快帮帮她如何选择吧。
Input
第一行输入一个正整数 ;
接下来  行中,第  行输入三个正整数  表示第  块水晶石的长宽高。注意可能有两个长得一模一样的水晶石,但是在这种情况下还是将它们视作是两块不同的水晶石。
Output
第一行请输出一个正整数 ,表示久莲选择的水晶球数量。
第二行请输出  个正整数,如果 ,请输出一个正整数  表示久莲选择的水晶石。如果 ,则请输出两个正整数  (用空格间隔),表示久莲希望亚瑟斯帮她将编号为  和  的水晶石融合成一块更大的水晶石,并选择用这块水晶石来打磨加工。请注意,这两块水晶石必须满足 “完美契合” 的条件,否则这个选择不合法。如果有多种最优的选择,则你可以输出任意一种合法的最优方案。
Hint
对于样例,如果久莲选择第六个水晶球,那么她可以打磨成半径为  的水晶球,这是最优的选择。

测试输入期待的输出时间限制内存限制额外进程
测试用例 1以文本方式显示
  1. 6↵
  2. 1 2 3↵
  3. 4 1 1↵
  4. 4 2 3↵
  5. 4 2 3↵
  6. 4 3 3↵
  7. 5 5 5↵
以文本方式显示
  1. 1↵
  2. 6↵
1秒64M0

思路

首先,定义了一个Crystal结构体,表示水晶的id和三个维度的值。以此保证后续排序后依旧能得到水晶的原位置。

struct Crystal {
    int id;
    int a, b, c;
};

然后,实现了一个rearrangeCrystals函数,用来对水晶的维度进行重新排列,使得a>b>c。

// 对水晶的维度进行重新排列,使得a>b>c
void rearrangeCrystals(vector<Crystal>& crystals) {
    for (int i = 0; i < crystals.size(); i++) {
        // 将水晶的维度存储在一个vector中
        vector<int> dimensions = { crystals[i].a, crystals[i].b, crystals[i].c };
        // 按降序对维度排序
        sort(dimensions.begin(), dimensions.end(), greater<int>());
        // 将排序后的维度重新赋值给水晶的a、b、c
        crystals[i].a = dimensions[0];
        crystals[i].b = dimensions[1];
        crystals[i].c = dimensions[2];
    }
}

接着,定义了一个compareCrystals函数,用来对水晶数组进行排序,排序的规则是优先按照a值降序排序,如果a值相等,则按照b值降序排序,如果b值相等,则按照c值降序排序。这样排序的目的是,尽量把a和b相同的水晶排列在一起,便于后续找到完美契合的面(全等长方形面)进行合并。

// 水晶比较函数
bool compareCrystals(const Crystal& c1, const Crystal& c2) {
    if (c1.a != c2.a) {
        return c1.a > c2.a;
    }
    else if (c1.b!= c2.b) {
        return c1.b > c2.b;
    }
    else {
        return c1.c > c2.c;
    }
}

在main函数中,首先读取输入的水晶数量n,并创建一个大小为n的水晶数组。然后,依次读取每个水晶的id和三个维度的值,并存储在水晶数组中。

 int n;
 cin >> n;

 vector<Crystal> crystals(n);

 // 读取水晶的id和三个维度的值
 for (int i = 0; i < n; i++) {
     crystals[i].id = i + 1;
     cin >> crystals[i].a >> crystals[i].b >> crystals[i].c;
 }

接下来,调用rearrangeCrystals函数对水晶的维度进行重新排列,并按照compareCrystals定义的规则对水晶进行排序。

  // 对水晶维度进行重新排列
  rearrangeCrystals(crystals);
  // 按照compareCrystals定义的规则对水晶进行排序
  sort(crystals.begin(), crystals.end(), compareCrystals);

然后,遍历水晶数组,找出不合并和合并的情况下能够形成最大半径的水晶对,并更新maxRadius、index和k的值。

    int k = 1; 
    int index=0; // 满足条件的水晶对的索引
    int maxRadius = crystals[0].c; // 最大的半径

    // 遍历水晶
    //不合并
    for (int i = 0; i < n; i++) {
        if (crystals[i].c > maxRadius) {
            maxRadius = crystals[i].c;
            index = i;
        }  
    }
    //合并
    for (int i = 0; i < n - 1; i++) {
        // 如果相邻的两个水晶的a和b值相等,说明可以形成一个水晶对
        if (crystals[i].a == crystals[i + 1].a && crystals[i].b == crystals[i + 1].b) {
            // 计算新的半径newRadius
            int newRadius = min(crystals[i].c + crystals[i + 1].c, crystals[i].b);
            // 如果新的半径大于maxRadius,更新maxRadius、index和k的值
            if (newRadius > maxRadius) {
                index = i;
                maxRadius = newRadius;
                k = 2;
            }
        }
    }

最后,根据k的值输出结果,如果k为1,则输出index对应的水晶id,如果k为2,则输出index和index+1对应的水晶id。

    cout << k << endl;

    // 根据k的值输出结果
    if (k == 1) {
        cout << crystals[index].id << endl;
    }
    else {
        cout << crystals[index].id << ' ' << crystals[index + 1].id << endl;
    }

    return 0;

注意事项 

  1. 水晶的维度排列:根据题目要求,需要对水晶的三个维度进行重新排列,使得a > b > c。这可以通过rearrangeCrystals函数来实现。

  2. 水晶的排序规则:根据题目要求,需要按照水晶的维度值进行排序,优先按照a值降序排序,如果a值相等,则按照b值降序排序,如果b值相等,则按照c值降序排序。这可以通过compareCrystals函数来定义排序规则。

  3. 水晶的合并条件:两个水晶能够合并成一个水晶对的条件是a值和b值相等。在遍历水晶数组时,需要注意判断相邻水晶的a和b值是否相等。

  4. 水晶对的半径计算:两个水晶能够合并成一个水晶对后,新的水晶对的半径计算方式为两个水晶的c值之和和较小的b值中的较小值。需要注意计算新的半径时,不要忽略掉较小的b值。

  5. 输出结果:根据题目要求,需要输出最大半径的水晶对的数量k和对应的水晶id。需要根据k的值来确定输出的格式。

C++整体代码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct Crystal {
    int id;
    int a, b, c;
};

// 对水晶的维度进行重新排列,使得a>b>c
void rearrangeCrystals(vector<Crystal>& crystals) {
    for (int i = 0; i < crystals.size(); i++) {
        // 将水晶的维度存储在一个vector中
        vector<int> dimensions = { crystals[i].a, crystals[i].b, crystals[i].c };
        // 按降序对维度排序
        sort(dimensions.begin(), dimensions.end(), greater<int>());
        // 将排序后的维度重新赋值给水晶的a、b、c
        crystals[i].a = dimensions[0];
        crystals[i].b = dimensions[1];
        crystals[i].c = dimensions[2];
    }
}

// 水晶比较函数
bool compareCrystals(const Crystal& c1, const Crystal& c2) {
    if (c1.a != c2.a) {
        return c1.a > c2.a;
    }
    else if (c1.b!= c2.b) {
        return c1.b > c2.b;
    }
    else {
        return c1.c > c2.c;
    }
}

int main() {
    int n;
    cin >> n;

    vector<Crystal> crystals(n);

    // 读取水晶的id和三个维度的值
    for (int i = 0; i < n; i++) {
        crystals[i].id = i + 1;
        cin >> crystals[i].a >> crystals[i].b >> crystals[i].c;
    }

    // 对水晶维度进行重新排列
    rearrangeCrystals(crystals);
    // 按照compareCrystals定义的规则对水晶进行排序
    sort(crystals.begin(), crystals.end(), compareCrystals);

    int k = 1; 
    int index=0; // 满足条件的水晶的索引
    int maxRadius = crystals[0].c; // 最大的半径

    // 遍历水晶
    //不合并的情况
    for (int i = 0; i < n; i++) {
        if (crystals[i].c > maxRadius) {
            maxRadius = crystals[i].c;
            index = i;
        }
        
    }
    //合并的情况
    for (int i = 0; i < n - 1; i++) {
        // 如果相邻的两个水晶的a和b值相等,说明可以合并
        if (crystals[i].a == crystals[i + 1].a && crystals[i].b == crystals[i + 1].b) {
            // 计算新的半径newRadius
            int newRadius = min(crystals[i].c + crystals[i + 1].c, crystals[i].b);
            // 如果新的半径大于maxRadius,更新maxRadius、index和k的值
            if (newRadius > maxRadius) {
                index = i;
                maxRadius = newRadius;
                k = 2;
            }
        }
    }

    cout << k << endl;

    // 根据k的值输出结果
    if (k == 1) {
        cout << crystals[index].id << endl;
    }
    else {
        cout << crystals[index].id << ' ' << crystals[index + 1].id << endl;
    }

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

榆榆欸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值