14.クリスタルボール
グレード
10
開始時間
2020年9月14日月曜日12:00
ディスカウント
0.8
割引時間
2020年9月21日月曜日00:00
遅延提出が可能
番号
閉店時間
2020年10月10日土曜日23:00
説明
同じ年齢の多くの女の子と同様に、Jiulenも水晶玉が好きです。
残り10日、彼の誕生日です。ジュレンは彼に彼に世界で最も大きくて見栄えの良い水晶玉を与えたいと思っています。彼女は彼の助けを求めることを望んで、宝石コレクターのアーサーを見つけました。アーサーズは素早く移動し、丁寧に集められた美しい水晶石を長さ、幅、高さの元々a、b、cであるn個取り出しました。アーサーは、ジュリアンがクリスタルストーンを贈り物の原料としてとることを約束しました。
同時に、アーサーには一種の魔法があります。2つの長方形のクリスタルストーンが片側で完全にフィットできる場合(完全なフィットは、2つの長方形の辺が等しいことを意味します)、それらを完全な大きなクリスタルにマージできます。石が実際に実現された場合、ジウリアンはより大きな水晶玉を磨くかもしれません!
ジュレンは彼に最も美しくて最大の水晶玉を与えたいと思っています。
1.知識の補足
まず、予熱の知識を一番上に置きます。この問題の実現は、並べ替えと切り離せません。最も重要なことは、構造を並べ替えることです。
c。学習中にバブリングソーティングとセレクションソーティングを学ぶべきだったc。忘れていないかわからないチキンウィングはまとめられているので復習できます。親密にポータルに送信されます:
ソート 挿入ソートを選択します
が、C ++ アルゴリズムライブラリはすでに優れたソートソート関数を実現しています。それは確かにあなたよりも速く、より優れた書き込みでなければならず、他の多くのタイプのソートを実現できます。はい、構造を並べ替えることができます。sort関数の使用に慣れていない場合は、まず、チキンウィングで要約されたこの記事を読む必要があります:並べ替えアルゴリズム| sort関数の使用、次にソリューションを確認してください。
2.前処理
この質問は非常に典型的な貪欲な質問であり、あなたがそれを理解したい場合、アイデアは非常に単純です。
データを処理しやすくするために、各立方体のデータを一緒に保存したいと思います(出力では立方体をマークする必要があるため、長さ、幅、高さのデータに加えてIDを記録する必要があります)。次に、構造結晶を使用して、立方体のデータを記述します。すべての立方体を格納するには、crl []構造配列が必要です。構造体の定義と構造体配列の宣言は次のとおりです。
struct crystal {
long long id; //水晶石的标号
long long length, width, height; //水晶石的长宽高
} crl[MAXN];
次に、いくつかの重要なポイントを分析します。
まず、水晶玉のサイズは直方体の最短辺によって完全に決まることを理解する必要があります。私たちの目標は、最短の辺を最長にすることです!
したがって、直方体(長さ、幅、高さ)の場合、処理を容易にするために、length> width> heightを指定する必要があります。このステップは、入力の処理中に実行できます。したがって、水晶玉をマージするときは、長さ*幅を選択するだけで、面をマージして最短の辺を増やすことができます。他の面をマージすることは無意味です、なぜなら最短の辺は本質的に増加しないからです!
3.コアアルゴリズム
前処理後、処理は2つの部分に分かれ
ます。1.マージせず
に、構造体配列の各立方体を1つずつトラバースし、最大の高さを見つけ、対応するID(数値)を記録します。
2.
最初に構造体配列をマージし、最初に長さキーワードで並べ替え、同じである場合は幅で並べ替え、同じである場合はheigjtで並べ替えます。
この方法でソートした後、長さ*幅の面をマージできる状況は、隣接する直方体にのみ表示されるため、隣接する直方体のマージを考慮するだけで済みます。ディスカッションの頻度が大幅に減少しました!
次に、隣接するボックスを結合できるかどうかを1つずつ列挙します。結合できる場合は、結合後の最短の辺を計算します。現在の最長および最短の辺よりも長い場合は、最長および最短の辺を更新し、対応する2つのIDを残します。
たとえば、直方体A1(長さ、幅、高さ1)と直方体A2(長さ、幅、高さ2)を組み合わせた結果は(長さ、幅、高さ1 +高さ2)です。マージ後の最も短い辺はmin(width、height1 + height2)であることに注意してください。
完全なコードは以下に添付されています:
#include <cstdio>
#include <algorithm>
#define MAXN 100050
using namespace std;
struct crystal {
long long id; //水晶石的标号
long long length, width, height; //水晶石的长宽高
} crl[MAXN];
bool cmpForStruct(struct crystal x, struct crystal y) {
if (x.length != y.length) //先按长度排序
return x.length > y.length;
else if (x.width != y.width) //再按宽度排序
return x.width > y.width;
else
return x.height > y.height; //最后按照高度排序
}
int main() {
long long n;
scanf("%lld\n", &n);
long long maxHeight = 0; //记录水晶石的最高高度
long long x = 0, y = 0; //记录选择水晶石的标号,当不可以合并时,只取x
for (long long i = 0; i < n; i++) {
long long temp[3]; //暂用来排序的数组
scanf("%lld%lld%lld", &temp[0], &temp[1], &temp[2]); //将输入的长宽高先放到数组temp中
sort(temp, temp + 3); //对temp数组[0,2]进行从小到大排序
//将输入更新到结构体数组中
crl[i].id = i + 1;
crl[i].length = temp[2];
crl[i].width = temp[1];
crl[i].height = temp[0];
//记录单个水晶石的最大高度
if (crl[i].height > maxHeight) {
maxHeight = crl[i].height;
x = crl[i].id; //记下标号
}
}
sort(crl, crl + n, cmpForStruct); //对水晶石结构体数组[0,n-1]进行排序,按照长、宽、高优先级排序
//依次讨论相邻水晶石合并的问题
for (long long i = 0; i < n - 1; i++) {
if (crl[i].length == crl[i + 1].length && crl[i].width == crl[i + 1].width) {
long long temp = crl[i].height + crl[i + 1].height; //合并
//计算合并之后的最短边
if (temp > crl[i].width)
temp = crl[i].width;
//更新两个水晶石的最大高度
if (temp > maxHeight) {
maxHeight = temp;
x = crl[i].id; //记下标号,不要以为下标+1就是id,你要记得我们对结构体数组排序过....
y = crl[i + 1].id;
}
}
}
if (y == 0)
printf("%d\n%lld\n", 1, x);
else
printf("%d\n%lld %lld\n", 2, x, y);
}
終わり
個人のパブリックアカウント「 チキンウィングプログラミング」に注意を払うことを歓迎します。ここには、真面目で行儀のよいコードファーマーがいます。
----最も行儀の良いブロガーであり、最も堅実なプログラマーになる----
それぞれの記事を注意深く書くことを目指し、通常はメモをプッシュ更新にまとめます〜