1. 程式人生 > >從演算法學起C語言--八枚硬幣

從演算法學起C語言--八枚硬幣

轉載請註明出處,謝謝~

背景說明:

現有八枚硬幣a,b,c,d,e,f,g,h,已知其中一枚硬幣是假幣,其重量不同於真幣,但不知道它是輕還是重,如何使用天平,以最少的比較次數,判斷哪枚硬幣是假幣,並得知它是輕還是重。

不用白話文解釋了吧。。。

首先果斷放棄兩兩比較的方法,可行但肯定不是最快解。

這裡我們用分段處理,將8個硬幣分成三組,第一組是1,2,3;第二組是4,5,6;第三組是7,8.我們比較前兩組的重量,如果相等,那麼假幣就存在與第三組中,再次比較第三組中兩個硬幣的重量,然後將較重的一個跟第一個硬幣比較重量,就可以得知那個硬幣是假幣,並且得知輕重了,其他的情況於此類此,下面用程式碼走一遍看看邏輯執行。

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);
	}
}
這個陣列中是從0開始的,那麼就從0開始定義硬幣
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);
	}
}

執行下:


完美執行~!