问题描述
有八枚银币a b c d e f g h ,已知其中一枚是假币,其重量不一样于真币,不知是较轻或较重,如何使用天平以最少的比较次数,肯定此枚假币和轻重.算法
算法思路
由于要求以最少的比较次数肯定假币和轻重,则咱们不能使用暴力破解此类的方法.咱们能够用决策树(decision tree)帮助分析与求解.思路是,将八枚硬币分红2份3个,对相应分法进行比较并取相应分法里比较的最少次数.
其中一种简单情况是,分红2份3个.两份是a+b+c和d+e+f.若是比较二者相等,则假币在g和h里,比较g和h,若是g比h重(或轻),再比较g和a(a是真币),若是g比a重,则g是重假币.ui
算法展现(代码已注释)
- 参数设置
void compare(int[], int, int, int);
void eightcoins(int[]);
void coins() {
int coins[8] = {3,3,3,3,4,3,3,3};
int i;
eightcoins(coins);
printf("\n列出全部钱币的重量:");
for (i = 0; i < 8; i++)
{
printf("%3d", coins[i]);
}
printf("\n");
}
复制代码
- 主要算法
//若0,1,2和3,4,5相同,则7,6其中有一个是假币
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);
}
}
//若0,1,2比3,4,5重,则6,7为真币
else if (coins[0] + coins[1] + coins[2] >
coins[3] + coins[4] + coins[5])
{
//若0,3和1,4同样重,则2,5其中有一个假币
if (coins[0]+ coins[3]== coins[1]+coins[4])
{
compare(coins, 2, 5, 7);
}
//若0,3比1,4重,因为1,2,3比4,5,6重且只有一个假币,由于3,1左右变换并未影响轻重.则0,4中有一个是假币
else if (coins[0] + coins[3] > coins[1] + coins[4])
{
compare(coins, 0, 4, 7);
}
//若0,3比1,4轻,因为1,2,3比4,5,6重且只有一个假币,1,3变换位置致使轻重变化,则1,3有一个是假币
else if (coins[0] + coins[3] < coins[1] + coins[4])
{
compare(coins, 1, 3, 7);
}
}
//若1,2,3比4,5,6轻.则7,8是真币
else if (coins[0] + coins[1] + coins[2] <
coins[3] + coins[4] + coins[5])
{
//若1,4和2,5相同,则3,6有一个是假币
if (coins[0] + coins[3] == coins[1] + coins[4])
{
compare(coins, 5, 2, 0);
}
//若1,4比2,5重,3,1调换位置致使关系变化,则3,1中有一是假币
else if (coins[0] + coins[3] > coins[1] + coins[4])
{
compare(coins, 3, 1, 0);
}
//若1,4比2,5轻,3,1调换位置为形成变化,则0,4有一个是假币
else if (coins[0] + coins[3] < coins[1] + coins[4])
{
compare(coins, 4, 0, 1);
}
}
复制代码
- 完整展现
#include <stdio.h>
#include <stdlib.h>
//silver coins - 八枚银币
void compare(int[], int, int, int);
void eightcoins(int[]);
void coins() {
int coins[8] = {3,3,3,3,4,3,3,3};
int i;
eightcoins(coins);
printf("\n列出全部钱币的重量:");
for (i = 0; i < 8; i++)
{
printf("%3d", coins[i]);
}
printf("\n");
}
void compare(int coins[], int i, int j, int k) {
if (coins[i] > coins[k])
{
printf("\n假币 %d 较重,重%d", i + 1,coins[i]);
}
else
{
printf("\n假币 %d 较轻,轻%d", j + 1,coins[j]);
}
}
void eightcoins(int coins[]) {
//若0,1,2和3,4,5相同,则7,6其中有一个是假币
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);
}
}
//若0,1,2比3,4,5重,则6,7为真币
else if (coins[0] + coins[1] + coins[2] >
coins[3] + coins[4] + coins[5])
{
//若0,3和1,4同样重,则2,5其中有一个假币
if (coins[0]+ coins[3]== coins[1]+coins[4])
{
compare(coins, 2, 5, 7);
}
//若0,3比1,4重,因为1,2,3比4,5,6重且只有一个假币,由于3,1左右变换并未影响轻重.则0,4中有一个是假币
else if (coins[0] + coins[3] > coins[1] + coins[4])
{
compare(coins, 0, 4, 7);
}
//若0,3比1,4轻,因为1,2,3比4,5,6重且只有一个假币,1,3变换位置致使轻重变化,则1,3有一个是假币
else if (coins[0] + coins[3] < coins[1] + coins[4])
{
compare(coins, 1, 3, 7);
}
}
//若1,2,3比4,5,6轻.则7,8是真币
else if (coins[0] + coins[1] + coins[2] <
coins[3] + coins[4] + coins[5])
{
//若1,4和2,5相同,则3,6有一个是假币
if (coins[0] + coins[3] == coins[1] + coins[4])
{
compare(coins, 5, 2, 0);
}
//若1,4比2,5重,3,1调换位置致使关系变化,则3,1中有一是假币
else if (coins[0] + coins[3] > coins[1] + coins[4])
{
compare(coins, 3, 1, 0);
}
//若1,4比2,5轻,3,1调换位置为形成变化,则0,4有一个是假币
else if (coins[0] + coins[3] < coins[1] + coins[4])
{
compare(coins, 4, 0, 1);
}
}
}
int main(void) {
coins();
return 0;
}
复制代码
算法描述
算法 | 时间复杂度 | 空间复杂度 |
---|---|---|
coins | O(n) | S(n) |
compare | O(1) | S(1) |
eightcoins | O(1) | S(1) |
总和 | O(n) | (n) |