Algorithm Gossip: 八枚银币
说明 现有八枚银币a b c d e f g h,已知其中一枚是假币,其重量不同于真币,但不知是较轻或
较重,如何使用天平以最少的比较次数,决定出哪枚是假币,并得知假币比真币较轻或较重。
解法 单就求假币的问题是不难,但问题限制使用最少的比较次数,所以我们不能以单纯的回
圈比较来求解,我们可以使用决策树(decision tree),使用分析与树状图来协助求解。一个简单
的状况是这样的,我们比较a+b+c与d+e+f ,如果相等,则假币必是g或h,我们先比较g或h哪个
较重,如果g较重,再与a比较(a 是真币),如果 g等于a,则g为真币,则h为假币,由于h比g轻
较重,如何使用天平以最少的比较次数,决定出哪枚是假币,并得知假币比真币较轻或较重。
解法 单就求假币的问题是不难,但问题限制使用最少的比较次数,所以我们不能以单纯的回
圈比较来求解,我们可以使用决策树(decision tree),使用分析与树状图来协助求解。一个简单
的状况是这样的,我们比较a+b+c与d+e+f ,如果相等,则假币必是g或h,我们先比较g或h哪个
较重,如果g较重,再与a比较(a 是真币),如果 g等于a,则g为真币,则h为假币,由于h比g轻
而 g是真币,则h假币的重量比真币轻。
#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输入假币重量(比10大或小):");
scanf("%d", &i);
coins[rand() % 8] = i;
eightcoins(coins);
printf("\n\n列出所有钱币重量:");
for(i = 0; i < 8; i++)
printf("%d ", coins[i]);
printf("\n");
return 0;
}
void compare(int coins[],int i, int j, int k) //coin[k]为真币,coin[i]>coin[j]
{
if(coins[i] > coins[k]) //coin[i]>coin[j]&&coin[i]>coin[k] ----->coin[i]为重的假币
printf("\n假币 %d 较重 ", i+1);
else //coin[i]>coin[j]&&coin[i]==coin[k]----->coin[j]为轻的假币
printf("\n假币 %d 较轻 ", j+1);
}
void eightcoins(int coins[])
{
if(coins[0]+coins[1]+coins[2] == //(a+b+c)=(d+e+f)
coins[3]+coins[4]+coins[5])
{
if(coins[6] > coins[7]) //g>h?(g>a?g:a):(h>a?h:a)
compare(coins, 6, 7, 0);
else //h>g?(h>a?h:a):(g>a?g:a)
compare(coins, 7, 6, 0);
}
else if(coins[0]+coins[1]+coins[2] > //(a+b+c)>(d+e+f)
coins[3]+coins[4]+coins[5])
{
if(coins[0]+coins[3] == coins[1]+coins[4]) //(a+e)=(d+b)
compare(coins, 2, 5, 0);
else if(coins[0]+coins[3] > coins[1]+coins[4]) //(a+e)>(d+b)
compare(coins, 0, 4, 1);
if(coins[0]+coins[3] < coins[1]+coins[4]) //(a+e)<(d+b)
compare(coins, 1, 3, 0);
}
else if(coins[0]+coins[1]+coins[2] < //(a+b+c)<(d+e+f)
coins[3]+coins[4]+coins[5])
{
if(coins[0]+coins[3] == coins[1]+coins[4]) //(a+e)>(d+b)
compare(coins, 5, 2, 0);
else if(coins[0]+coins[3] > coins[1]+coins[4]) //(a+e)>(d+b)
compare(coins, 3, 1, 0);
if(coins[0]+coins[3] < coins[1]+coins[4]) //(a+e)<(d+b)
compare(coins, 4, 0, 1);
}
}
#include <iostream>
using namespace std;
int Judge(int coin[])
{
if(coin[0]+coin[1]+coin[2] > coin[3]+coin[4]+coin[5]) //(a+b+c)>(d+e+f)
{
if(coin[0]+coin[4] > coin[3]+coin[1]) //(a+e)>(d+b)
return coin[0] > coin[7]? 0:3; //coin[0]>coin[7] -->coin[0]为重的假币,coin[0]==coin[7] -->coin[3]为轻的假币
if(coin[0]+coin[4] == coin[3]+coin[1]) //(a+e)=(d+b)
return coin[2] > coin[7]? 2:5; //coin[2]>coin[7] -->coin[2]为重的假币,coin[2]==coin[7] -->coin[5]为轻的假币
else //(a+e)=(d+b)
return coin[1] > coin[7]? 1:4; //coin[1]>coin[7] -->coin[1]为重的假币,coin[1]==coin[7] -->coin[4]为轻的假币
}
if(coin[0]+coin[1]+coin[2] == coin[3]+coin[4]+coin[5]) //(a+b+c)=(d+e+f)
return coin[6] >coin [7]? (coin[6] > coin[0]? 6:7):(coin[7] > coin[0]? 7:6); //g>h?(g>a?g:a):(h>a?h:a)
else //(a+b+c)<(d+e+f)
{
if(coin[0]+coin[4] > coin[3]+coin[1]) //(a+e)>(d+b)
return coin[4] > coin[7]? 4:1; //coin[4]>coin[7] -->coin[4]为重的假币,coin[4]==coin[7] -->coin[1]为轻的假币
if(coin[0]+coin[4] == coin[3]+coin[1]) //(a+e)=(d+b)
return coin[5] > coin[7]? 5:2; //coin[5]>coin[7] -->coin[5]为重的假币,coin[5]==coin[7] -->coin[2]为轻的假币
else //(a+e)<(d+b)
return coin[3] > coin[7]? 3:0; //coin[3]>coin[7] -->coin[3]为重的假币,coin[3]==coin[7] -->coin[0]为轻的假币
}
}
int main()
{
int coin[8],nocoin;
cout<<"请输入八枚硬币(a--h)各自的重量,七个真币,重量一样,一个假币,重量与其他七个不同"<<endl;
for(int i =0; i<8; i++)
{
cout<<(char)(i+97)<<"=";
cin>>coin[i];
}
nocoin=Judge(coin);
cout<<"假币为:"<<(char)(nocoin+97)<<endl;
return 0;
}