算法: Silver Coins -八枚银币问题

问题描述


有八枚银币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)
相关文章
相关标签/搜索