题目:
一个装有16枚硬币的袋子,16枚硬币中有一个是伪造的,并且那个伪造的硬币比真的硬币要轻。现有一台可用来比较两组硬币重量的仪器,请使用分治法设计一个算法,可以找出那枚伪造的硬币。
首先建立一个有16个int数据类型的数组,模拟16枚硬币,真币赋为1,假币赋为0。根据二分搜索法的原理,设计算法代码如下:
// Chapter7_3.cpp : Defines the entry point for the application.
// 用分治法设计一个算法,找出伪造硬币
// 一个装有16枚硬币的袋子,16枚硬币中有一个是伪造的,并且那个伪造的硬币比真的硬币要轻。
// 现有一台可用来比较两组硬币重量的仪器,请使用分治法设计一个算法,可以找出那枚伪造的硬币。
#include "stdafx.h"
#include<iostream>
using namespace std;
const int total = 16; //硬币总数
int calltimes = 0; //查找次数
//求重量和
int weight(int arr[], int Begin, int End)
{
int sum = 0;
for(int i=Begin; i<=End;i++)
sum += arr[i];
return sum;
}
//找假币
int findFake(int arr[], int Begin, int End)
{
calltimes++;
cout << "第 " << calltimes << " 次查找" << endl;
//如果最后二分到只有两个数时
if(End-Begin == 1)
{
if(arr[Begin] >= arr[End]) //硬币在后半部分
return End;
else
return Begin;
}
else
{
if(weight(arr,Begin,(Begin+End)/2) > weight(arr,(Begin+End)/2+1,End)) //硬币在后半部分
{
Begin = (Begin+End)/2+1;
cout << "银币在后半部分" << endl;
}
else
{
End = (Begin+End)/2;
cout << "银币在前半部分" << endl;
}
return findFake(arr, Begin, End);
}
}
int main()
{
int coin[total],fake;
//模拟硬币真伪,1为真硬币,0为假硬币
for(int i=0;i<total;i++)
coin[i] = 1;
coin[3] = 0; //假设第四枚硬币为假
fake = findFake(coin, 0, total-1)+1;
cout << "the fake coin is number " << fake << endl;
system("pause");
return 0;
}
其中,
coin[3] = 0; //假设第四枚硬币为假
是假定某个元素为假币,这里是假设第4枚是假币(数组角标从0开始)。
运行结果如下:
将假币换成第9个试试,即
coin[8] = 0; //假设第九枚硬币为假
运行结果如下: