アルゴリズム偽造コイン問題 (分割統治)

この記事は Google 翻訳を使用して処理されました

問題の説明

コインは $n$ 枚あり、そのうち 1 枚は偽造コインであり、偽造コインの方が軽いことが分かっています。今では残高は 1 つだけなので、できるだけ少ない比較で偽造コインを見つける必要があります。

問題分析

$n$ 枚のコインを 2 つの等しい部分に分割します。

  1. $n$ が偶数の場合、最初の部分と2番目の部分、$1\cdots\frac{n}{2}$ と $\frac{n}{2}+1\cdots n$ を2つのスケールの端と端を照らします。軽い方の端に偽造コインが含まれています。同じ方法を使用して、コインの軽い部分にある偽造コインを見つけます。
  2. $n$ が奇数の場合、最初と最後の部分 $1\cdots\frac{n-1}{2}$ と $\frac{n+1}{2}+1\cdots n$ を、天秤の軽い方の端に偽造コインがあります。同じ方法を使用して、コインの軽い部分にある偽造コインを見つけ続けます。両端の重さが同じであれば、真ん中のコインは偽造コインです。つまり、$\frac{n+1}{2}$ 枚のコインは偽造品である。

Cコード

#include <stdio.h>

// coins:重量配列   first,last:配列の最初と最後の添え字
int getCounterfeitCoin(int *coins, int first, int last);

int main(void){
    int coins[10] = {2,2,1,2,2,2,2,2,2,2};
    int tmp = getCounterfeitCoin(coins, 0, 9);
    printf("%d は偽造コインです\n",tmp+1);
    return 0;
}

int getCounterfeitCoin(int *coins, int first, int last){
    int firstSum=0; int lastSum=0;
    int i;

    // 残りコインは2枚のみ
    if(first == last -1){
        if(coins[first] < coins[last])
            return first;
        return last;
    }

    // 偶数枚のコイン
    if ((last-first+1)%2 == 0){
        for(i=first; i<first+(last-first)/2+1; i++){
            firstSum += coins[i];
        }
        for(i=first+(last-first)/2+1; i<last+1; i++){
            lastSum += coins[i];
        }

        if(firstSum < lastSum){
            return getCounterfeitCoin(coins, first, first+(last-first)/2);
        }else{
            return getCounterfeitCoin(coins, first+(last-first)/2+1, last);
        }
    }else{  // 奇数のコイン
        for(i=first; i<first+(last-first)/2; i++){
            firstSum += coins[i];
        }
        for(i=first+(last-first)/2+1; i<last+1; i++){
            lastSum += coins[i];
        }

        if(firstSum < lastSum){
            return getCounterfeitCoin(coins, first, first+(last-first)/2-1);
        }else if(firstSum > lastSum){
            return getCounterfeitCoin(coins, first+(last-first)/2+1, last);
        }else{
            return first+(last-first)/2;
        }
    }
}

Hugo で構築されています。 | テーマ StackJimmy によって設計されています。