効率的な表現のための刺激的な使用の少ないコード
題名
NアイテムのZhonglian L1とバックパックMの容量を考慮して、各バックパックは最大2つのアイテムを保持する必要があり、すべてのアイテムを保持するのに必要なバックパックの数。
問題解決プロセス
バックパックとの最初の接触。
元のアイデアは、降順で並べ替え、最大値からトラバースし、バックパックにパックできる2つのオブジェクトが見つかるまでiの後にjからトラバースします。見つからない場合、最大値は個別にパックされます。時間の複雑さはO(n ^ 2)、タイムアウト、複雑です。
インターネットを検索した後、より最適化されたアイデアは次のとおりです。昇順で並べ替え、iの最小値からトラバース、jの最大値からトラバース。2つの合計が条件を満たす場合はパックし、そうでない場合は大きい値を個別にパックします。
それで私は考え始めました、なぜソートを調整するだけで、時間の複雑さとコードの複雑さがそれほど違うのですか?
ブレーンストーミングの後、次の結論に達しました:
降順で並べ替えると、各トラバーサルの後に、条件を満たさない人はスキップされ、判断のサイクルに何度も参加します。
また、昇順で並べ替えると、条件が満たされているかどうかに関係なく、すべてのトラバーサルが、処理されるため、効率が大幅に向上します(単純な二分法、分割統治の原則)。
また、トラバースするたびに後者が対応する処理を実行するため、判断がシーケンスの両端で制御されるたびに、アイデアがはるかに単純になります。
質問のACは、多くの場合、単一の思考の範囲内にあることがわかります。より柔軟に考えると、問題をより速くより適切に解決できます。
以下のコードを貼り付けます。
N <= 10 ^ 5ですが、a [100005]に設定されたアレイはバーストすることに注意してください。最後に、成功したACである[100010]に変更されました。それもちょっとしたトリックです。
#include<bits/stdc++.h>
using namespace std;
int a[100010];
int main() {
ios::sync_with_stdio(false);
int T; cin>>T; while(T--) {
int n, num; cin>>n>>num;
for(int i = 0; i < n; i++) cin>>a[i];
sort(a, a+n);
int i = 0, j = n-1, sum = 0;
while(i <= j) {
if(i == j) {
sum++; break; }
if(a[i]+a[j] <= num) {
i++; j--; sum++; }
else {
j--; sum++; }
}
cout << sum << endl << (T?"\n":"");
}
return 0; }