從演算法學起C語言--八枚硬幣
轉載請註明出處,謝謝~
背景說明:
現有八枚硬幣a,b,c,d,e,f,g,h,已知其中一枚硬幣是假幣,其重量不同於真幣,但不知道它是輕還是重,如何使用天平,以最少的比較次數,判斷哪枚硬幣是假幣,並得知它是輕還是重。
不用白話文解釋了吧。。。
首先果斷放棄兩兩比較的方法,可行但肯定不是最快解。
這裡我們用分段處理,將8個硬幣分成三組,第一組是1,2,3;第二組是4,5,6;第三組是7,8.我們比較前兩組的重量,如果相等,那麼假幣就存在與第三組中,再次比較第三組中兩個硬幣的重量,然後將較重的一個跟第一個硬幣比較重量,就可以得知那個硬幣是假幣,並且得知輕重了,其他的情況於此類此,下面用程式碼走一遍看看邏輯執行。
這個陣列中是從0開始的,那麼就從0開始定義硬幣void compare(int coins[],int i,int j, int k) { if(coins[i] > coins[k]) printf("\n假幣 %d 較重",i+1); else printf("\n假幣 %d 較輕",j+1); } void eightcoins(int coins[]) { if (coins[0]+coins[1]+coins[2] == coins[3]+coins[4]+coins[5]) { if(coins[6] > coins[7]) compare(coins,6,7,0); else compare(coins,7,6,0); }else if (coins[0]+coins[1]+coins[2] > coins[3]+coins[4]+coins[5]){ if(coins[0]+coins[3] == coins[1]+coins[4]) compare(coins,2,5,0); else if(coins[0]+coins[3] > coins[1]+coins[4]) compare(coins,0,4,1); else if(coins[0]+coins[3] < coins[1]+coins[4]) compare(coins,1,3,0); }else if (coins[0]+coins[1]+coins[2] < coins[3]+coins[4]+coins[5]){ if(coins[0]+coins[3] == coins[0]+coins[4]) compare(coins,5,2,0); else if(coins[0]+coins[3] > coins[1]+coins[4]) compare(coins,3,1,0); else if(coins[0]+coins[3] < coins[1]+coins[4]) compare(coins,4,0,1); } }
1.如果0,1,2的重量 = 3,4,5的重量,說明假幣不在這6枚中,比較6,7的重量,如果6 > 7,則比較6,0的重量,如果6重,說明6是假幣,且較重。如果6不大於7,那麼只可能出現6 = 0,因為如果6>7,假設6<0,則可得7<0,說明有兩枚硬幣是假幣,與題設不符,所以當6 = 0時,可得7為假幣,且較輕。
2.如果0+1+2 > 3+4+5,說明6和7不是假幣,那麼判斷0+3和1+4的輕重,如果相等,判斷2和0的重量,邏輯同上。如果0+3 > 1+4,說明2和5不是假幣,判斷0和1的重量,如果0>1,如果1是假幣,則1輕,但又已知1+2+0 > 3+4+5,所以不成立,可得0是假幣,較重。如果0=1,假設3是假幣,3較重,那麼與一直相悖,不成立,所以可得4是假幣,且較輕。如果0<1,與已知0+3>1+4相悖,所以不會出現。如果0+3
< 1+4,那麼比較1與0的重量,邏輯同上相似。
3.如果0+1+2 < 3+4+5 ,同樣比較0+3與1+4,若相等,比較5,0;如果0+3>1+4,比較3,0;若0+3<1+4,比較4,1.邏輯同上。
比較的時候其實比較誰並不是固定的,例如最後的3步驟總,若0+3 = 1+4 ,可以比較5和0,而當0+3 > 1+4,可以比較0,1;0+3 < 1+4,可以比較1,0.,0>1的話,1是假幣,0=1的話,3是假幣,同樣,0+3 < 1+4時,我們可以比較1和0,1>0的話,0是假幣,1=0的話,4是假幣。
下面貼上完整程式碼:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void compare(int[] ,int, int ,int);
void eightcoins(int[]);
int main(void)
{
int coins[8] = {0};
int i;
srand(time(NULL));//使用系統時間作為隨機數種子,防止每次產生相同的隨機數
for (i=0;i<8;i++)
{
coins[i] = 10;
}
printf("\n 輸入假幣重量(比十大或小) :\n");
scanf("%d",&i);
coins[rand()%8] = i;//也可以這麼寫1 + (n * rand() / (RAND_MAX + 1))
eightcoins(coins);
printf("\n\n列出所有硬幣重量:\n");
for(i = 0 ; i<8 ; i++)
printf("%d",coins[i]);
printf("\n");
system("pause");
return 0;
}
void compare(int coins[],int i,int j, int k)
{
if(coins[i] > coins[k])
printf("\n假幣 %d 較重",i+1);
else
printf("\n假幣 %d 較輕",j+1);
}
void eightcoins(int coins[])
{
if (coins[0]+coins[1]+coins[2] == coins[3]+coins[4]+coins[5])
{
if(coins[6] > coins[7])
compare(coins,6,7,0);
else
compare(coins,7,6,0);
}else if (coins[0]+coins[1]+coins[2] > coins[3]+coins[4]+coins[5]){
if(coins[0]+coins[3] == coins[1]+coins[4])
compare(coins,2,5,0);
else if(coins[0]+coins[3] > coins[1]+coins[4])
compare(coins,0,4,1);
else if(coins[0]+coins[3] < coins[1]+coins[4])
compare(coins,1,3,0);
}else if (coins[0]+coins[1]+coins[2] < coins[3]+coins[4]+coins[5]){
if(coins[0]+coins[3] == coins[0]+coins[4])
compare(coins,5,2,0);
else if(coins[0]+coins[3] > coins[1]+coins[4])
compare(coins,3,1,0);
else if(coins[0]+coins[3] < coins[1]+coins[4])
compare(coins,4,0,1);
}
}
執行下:
完美執行~!