在120枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的质量不同,但不知道假币与真币相比是较轻还是较重。可以通过一台天平来任意比较两组硬币,最坏情况下,能不能通过5次比较检测出这枚假币?给出代码,用C++实现
时间: 2024-10-15 15:09:16 浏览: 125
在最坏的情况下,可以利用二分查找法和贪心策略在五次比较内找出这枚假币。我们可以将硬币分为三组每组40枚、41枚(一组比其他多一),然后按照以下步骤操作:
1. 第一次比较:将两组40枚硬币放在天平两端,如果平衡,则假币在未称量的41枚中;如果不平衡,假币在较轻或较重的那一组。
2. 第二次比较:如果假币在41枚中,取那41枚的一半(20枚+11枚),分别放在天平两端,若平衡,假币在未称量的11枚里,否则在较轻或较重的那一堆。
3. 第三次比较:取剩余那堆的11枚硬币中的7枚(3+4)与另一组(如第一次剩余的是20枚,则拿这20枚)进行比较。如果平衡,假币在未称量的4枚里;若不平衡,假币在较轻或较重的一侧。
4. 第四次比较:确定了假币所在的区域,再取3枚(如果是在7枚中找到的,取2+1;如果是在4枚中找到的,取3枚)进行称量。同样,平衡则剩下的那枚就是假币,不平衡则假币在较轻或较重的一端。
5. 第五次比较:最后一次只需对比剩余的2枚硬币(如果第四步有剩余的话),如果天平平衡,则未被称过的那一枚就是假币。
以下是简单的C++代码实现:
```cpp
#include <iostream>
using namespace std;
int main() {
int coins[120];
// 假设初始状态全部硬币序号从0到119
for (int i = 0; i < 120; i++) {
coins[i] = i;
}
bool foundFakeCoin = false;
for (int round = 0; round < 5 && !foundFakeCoin; round++) {
// 分组并比较
int group1 = coins[round * 40 : round * 40 + 40];
int group2 = coins[round * 41 : round * 41 + 41];
if (compareCoins(group1, group2)) { // 比较并更新假币位置
if (round == 4) { // 如果第五轮还无法确定,说明假币未被区分
cout << "无法确定假币位置" << endl;
break;
}
foundFakeCoin = true;
} else {
// 更新分组范围
int nextGroupSize = 20 + (round % 2 == 0 ? 11 : 3);
int start = round * 41 + (round % 2 == 0 ? 0 : 40);
coins = coins + start;
coins.resize(120 - start);
for (int i = 0; i < nextGroupSize; i++) {
coins[start + i] = coins[start + i + (nextGroupSize / 2)];
}
}
}
if (foundFakeCoin) {
cout << "假币序号为:" << coins[0] << endl;
}
return 0;
}
bool compareCoins(int group1[], int group2[]) {
// 省略实际的天平比较逻辑,这里假设group1比group2轻代表假币在group1
// ... 进行实际的比较,返回true表示group1中有假币
}
```
这个代码简化了比较过程,实际应用中需要处理具体的天平比较逻辑。请注意,上述代码仅作为思路示例,并未包含所有细节,实际编写时还需要完善天平比较部分。
阅读全文