一、算法介绍
有n个金币,其中一个是假币。这个假币的重量比真币的重量要轻一点,所有n-1个金币的重量是一样的。现在有一架天平,设计高效的算法(用最少的使用天平次数)找出那个假的金币。
二、算法思想
每次平均分三堆的结果可能有:余数0 余数1 余数2
- 余数0: 平均分,任选两堆(堆1+堆2)比较,
如果平衡: 堆3含假币;
如果不平衡: 比较堆1和堆3,
如果平衡: 堆2含假币;
如果不平衡: 堆1含假币;
- 余数1: 平均分后得到3堆+1个硬币,任选两堆(堆1+堆2)比较,
如果平衡: 比较堆1和堆3,
如果平衡: 剩余的单个硬币为假,
如果不平衡: 堆3为含假币的堆
如果不平衡: 比较堆1和堆3,
如果平衡: 堆2含假币
如果不平衡: 堆1含假币
- 余数2: 平均分后得到3堆+2个硬币,任选两堆(堆1+堆2)比较,
如果平衡: 比较堆1和堆3
如果平衡: 假币在两个单个硬币中,这两个硬币必然是不平衡的,这时从堆中找出任意一枚硬币,从两个单个硬币中拿出硬币1进行比较
如果平衡:假币为币2
如果不平衡:假币为币1
如果不平衡: 堆3为含假币的堆
如果不平衡: 比较堆1和堆3
如果平衡: 堆2含假币
如果不平衡: 堆1含假币
三、实验代码
#include <iostream>
#include <math.h>
using namespace std;
#define numnum 14
int coin[numnum] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3};
/*计算总重量 */
int Weight_Sum(int arr[], int low, int high)
{
int sum = 0;
for (int i = low; i <= high; i++)
sum += arr[i];
return sum;
}
/* 称硬币,找出假币数组下标*/
int Weight_Coin(int coin[], int coinNum, int low, int high)
{
int k = floor(coinNum / 3);
int r = coinNum % 3;
if (r == 0)
{
int index = 0;
int A, B, C;
A = Weight_Sum(coin, low, low + k - 1);
B = Weight_Sum(coin, low + k, low + 2 * k - 1);
C = Weight_Sum(coin, low + 2 * k, high);
if (coinNum == 3)
{
if (A == B)
{
index = high;
}
else if (A == C)
{
index = high - 1;
}
else
{
index = low;
}
return index;
}
else
{
if (A == B)
{
index = Weight_Coin(coin, k, low + 2 * k, high);
return index;
}
else if (A == C)
{
index = Weight_Coin(coin, k, low + k, low + 2 * k - 1);
return index;
}
else
{
index = Weight_Coin(coin, k, low, k - 1);
return index;
}
}
}
if (r == 1)
{
int index = high;
int A, B, C;
A = Weight_Sum(coin, low, low + k - 1);
B = Weight_Sum(coin, low + k, low + 2 * k - 1);
C = Weight_Sum(coin, low + 2 * k, high - 1);
if (coinNum == 1)
{
return index;
}
else
{
if (A == B)
{
if (A == C)
return index;
if ((A < C || A > C))
{
index = Weight_Coin(coin, k, low + 2 * k, high - 1);
return index;
}
}
else if (A == C)
{
index = Weight_Coin(coin, k, low + k, low + 2 * k - 1);
return index;
}
else
{
index = Weight_Coin(coin, k, low, k - 1);
return index;
}
}
}
if (r == 2)
{
int index = 0;
int index1 = high - 1;
int index2 = high;
int A, B, C;
A = Weight_Sum(coin, low, low + k - 1);
B = Weight_Sum(coin, low + k, low + 2 * k - 1);
C = Weight_Sum(coin, low + 2 * k, high - 2);
if (coinNum < 3)
{
int campare1; //参照物
if (high != numnum - 1)
campare1 = coin[numnum - 1];
else
campare1 = coin[0];
if (coin[high] == campare1)
index = low;
if (coin[low] == campare1)
index = high;
return index;
}
else
{
if (A == B && B == C)
{
int cam = coin[0];
if (coin[high - 1] == cam)
index = index2;
if (coin[high] == cam)
index = index1;
return index;
}
else if ((A == B) && (A < C || A > C))
{
index = Weight_Coin(coin, k, low + 2 * k, high - 2);
return index;
}
else if (A == C)
{
index = Weight_Coin(coin, k, low + k, low + 2 * k - 1);
return index;
}
else
{
index = Weight_Coin(coin, k, low, k - 1);
return index;
}
}
}
return 0;
}
/*判断假币质量*/
void Judge(int number)
{
int campareble;
if (number != numnum - 1)
campareble = coin[numnum - 1];
else
campareble = coin[0];
if (coin[number] < campareble)
cout << "假币的位置为 " << number << " 并且假币偏轻" << endl;
else if (coin[number] > campareble)
cout << "假币的位置为 " << number << " 并且假币偏重" << endl;
else
cout << "参照出错" << endl;
}
int main()
{
if (numnum < 3)
{
cout << "数量太少,无法比较" << endl;
return 0;
}
int number;
number = Weight_Coin(coin, numnum, 0, numnum - 1);
Judge(number);
return 0;
}
四、实验结论
1、
2、
3、
参考博文https://blog.youkuaiyun.com/ngl158358/article/details/79953769