演習7人のケーブルの幹部の問題解決の半分

トピック出典:第VII章演習7(ノースイースタンヨーロッパ2001)「の情報は、オリンピックを渡すために必要な」

タイトル説明

ワンダーランドの住民は、地域大会のプログラムを開催することを決定しました。審判委員会は、ボランティアによって完全にほとんどの一度だけのゲームの歴史の中を整理するとのコミットメントを作曲しました。彼らはすべての単一の中央サーバに接続しようとしている、一緒にスター型トポロジでコンピュータプレイヤーを接続することを決めました。この競争を整理するために審判委員会の委員長が、等間隔サーバーの周囲に配置されたコンピュータの周りのすべてのプレイヤーに提案し、完全に公平です。
ケーブルの購入のために、審判委員会は、等しい長さのケーブルの特定の数を提供するために必要な、ローカルネットワークソリューションプロバイダに連絡しました。審判委員会は、できるだけ長いケーブルを期待しているように限り選手の一部として、缶の間の距離。
同社のケーブルの幹部は、この作業に着手します。彼は(センチメートルの精度)各目録ネットワークケーブルの長さを知っていた、そして限り(センチメートルの精度)に必要なケーブル長として、彼はケーブルを切断する作業を完了することができるようになりますことを彼に告げました。しかし、この時、損失でケーブルの幹部になります知っていない必要なケーブルの長さは、。
あなたは、ネットワークケーブルの数を指定することができ、ケーブルカットの目録上のネットワークケーブルの幹部最長のケーブルの長さ、および長さをクリックして判断するのに役立つプログラムを記述する必要があります。

入力形式

最初の行は、単一のスペースで区切られた2つの整数N及びKを含んでいます。N(1 <= Nは<= 10000) 、K(1 <= K <ケーブルの在庫数である = 10000)は、 必要なケーブルの数です。
各ケーブル長(:M単位)の株式の数の次のNライン。ケーブルのすべての長さは100キロまで、少なくとも1メートルです。すべての入力の長さは、すなわち、小数点第3位を保持し、センチメートルに正確です。

出力フォーマット

有能なケーブルは、ケーブルネットワークインベントリ最長の長さ(:M単位)からワイヤの指定された数を切り出すことができます。小数点以下2桁に予約されていセンチに正確でなければなりません。
あなたはケーブルの少なくとも1センチメートル指定された数の長さを得ることができない場合は、それを出力しなければならない(引用符なし)「0.00」。

サンプル入力

4 11
8.02
7.43
4.57
5.39

サンプル出力

2.00

トピック分析

この質問は、「最小限に抑えるために、最大」実際には同じ溶液、ほぼ正確に同じ問題を抱えています。また、半分の答えですが、この質問は、範囲内の実の二分法です。

整数の半分

整数の半分のために、擬似コードの半分は、私たちはそれを実現します:

int L = 左边界, R = 右边界, res = -1;
while (L <= R) {
    int mid = (L + R) / 2;
    if (条件满足) {
        res = mid;
        L = mid + 1; // 或者 R = mid - 1;
    }
    else {
        R = mid - 1; // 或者 L = mid + 1;
    }
}

サイクルの終わりには、\(RES \)メモリは、私たちがお答えしたいということです。

リアルタイム半分

実数ができないバイナリため\(L =ミッド+ 1; \) または\(R =ミッド- 1; \) ような動作、および使用することはできません\(L \ルRは\)周期的にするための条件を決定します。
代わりに、使用\ - (R Lの\)我々は小数点応答する場合、例えば、特定の臨界値より小さいと、\(3 \)を、次いでIは、条件満足する10 ^ LT \(R- L \を { - 4} \)ときに終了ループので、リリースサイクルの場合は、(Lの\)\\(R&LT \)保持\(3 \)下ケースを分別結果は同じです。
実数、擬似コードの半分のために我々はその二分法を実現します:

double L = 左边界, R = 右边界;  // 注意这里是实数的表示,L和R最好开成double
while (R - L >= 1e-4) { // 1e-4是科学计数法的表示,用于表示1乘10的-4次方
    double mid = (L + R) / 2.0;     // 注意这里的mid也是实数
    if (条件满足) {
        L = mid;    // 或者 R = mid;
    }
    else {
        R = mid;    // 或者 L = mid;
    }
}

最後に、確かにいることを確認することができ、サイクルタイムを終了\(Lの\)\(R \)ギャップは非常に小さく、そして我々の出力\(Lの\)\(R \)は、正確にする(3 \)\小数点以下の桁数をその結果。
注:バイナリ実数では、使用して\を(L =ミッド\)または\(R&LT = MID \) 代わりに整数の二点で\(L =ミッド+ 1 \ ) または\(R =ミッド1 \ )この細部に注意を払うこと。
注:タイトルは100キロの右の境界線である、それは処理中に、この細部に注意を払うように、10万メートルです。

次のようにコードは次のとおりです。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int n, k;
double a[maxn];

bool check(double len) {
    int cnt = 0;
    for (int i = 0; i < n; i ++) cnt += floor(a[i] / len);
    return cnt >= k;
}

int main() {
    cin >> n >> k;
    for (int i = 0; i < n; i ++) cin >> a[i];
    double L = 0.0, R = 100000.0;
    while (R - L >= 1e-4) {
        double mid = (L + R) / 2.0;
        if (check(mid)) L = mid;
        else R = mid;
    }
    printf("%.2lf\n", L);
    return 0;
}

おすすめ

転載: www.cnblogs.com/zifeiynoip/p/11450633.html