题目
Description
和许多同龄女孩子一样,久莲也喜欢水晶球。
还有 天,就是心心念念的他生日了。
久莲希望把全世界最大最好看的水晶球送给他。
她找到了宝石收藏家亚瑟斯,希望能够寻求他的帮助。
亚瑟斯很快被打动了,拿出了精心收集的 块美丽的水晶石,这些水晶石初始是长宽高分别为 的长方体。亚瑟斯许诺久莲可以从中取走 块水晶石作为她礼物的原材料。
同时亚瑟斯有一种魔法,如果这两块长方形水晶石在某一个面能够完美的契合在一起(完美的契合是指这两个长方形面全等),那么可以将它们融合成一块完整的大石头,如果真的实现的话,那么久莲就可能打磨出更大的水晶球啦!
久莲太希望把最美最大的水晶球送给他了,你快帮帮她如何选择吧。
Input
第一行输入一个正整数 ;
接下来 行中,第 行输入三个正整数 表示第 块水晶石的长宽高。注意可能有两个长得一模一样的水晶石,但是在这种情况下还是将它们视作是两块不同的水晶石。
Output
第一行请输出一个正整数 ,表示久莲选择的水晶球数量。
第二行请输出 个正整数,如果 ,请输出一个正整数 表示久莲选择的水晶石。如果 ,则请输出两个正整数 (用空格间隔),表示久莲希望亚瑟斯帮她将编号为 和 的水晶石融合成一块更大的水晶石,并选择用这块水晶石来打磨加工。请注意,这两块水晶石必须满足 “完美契合” 的条件,否则这个选择不合法。如果有多种最优的选择,则你可以输出任意一种合法的最优方案。
Hint
对于样例,如果久莲选择第六个水晶球,那么她可以打磨成半径为 的水晶球,这是最优的选择。
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
思路
首先,定义了一个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;
注意事项
-
水晶的维度排列:根据题目要求,需要对水晶的三个维度进行重新排列,使得a > b > c。这可以通过rearrangeCrystals函数来实现。
-
水晶的排序规则:根据题目要求,需要按照水晶的维度值进行排序,优先按照a值降序排序,如果a值相等,则按照b值降序排序,如果b值相等,则按照c值降序排序。这可以通过compareCrystals函数来定义排序规则。
-
水晶的合并条件:两个水晶能够合并成一个水晶对的条件是a值和b值相等。在遍历水晶数组时,需要注意判断相邻水晶的a和b值是否相等。
-
水晶对的半径计算:两个水晶能够合并成一个水晶对后,新的水晶对的半径计算方式为两个水晶的c值之和和较小的b值中的较小值。需要注意计算新的半径时,不要忽略掉较小的b值。
-
输出结果:根据题目要求,需要输出最大半径的水晶对的数量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;
}