简要介绍:
分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成。下面的硬币问题就是分治算法的一种典型算法题。
●硬币问题
在下面我们将硬币分为1和0两个值,1为真硬币,0为假硬币。找偶数枚硬币和奇数枚硬币将其随机排成一列,其中有一个假硬币,用分治算法寻找出这枚假硬币所在的位置。如下两图所示:
当硬币个数为偶数时(10枚):
当硬币个数为奇数时(13枚):
代码实现:
#include<iostream> using namespace std; #define maxsize 20 class fenzhi { public: int falsecoin(int low, int high); void showresult(); int num; int coin[maxsize]; int result; }; int fenzhi::falsecoin(int low, int high) { int sum1=0; int sum2=0; int sum3=0; if (low + 1 == high) //只有两枚硬币 { if (coin[low] < coin[high]) { result = low + 1; return result; } else { result = high + 1; return result; } } //分治算法 if((high-low+1)%2==0) //n是偶数 { for (int i = low; i <= low+(high-low)/2; i++) { sum1 += coin[i];//前半段和 } for (int j = low + (high - low) / 2+1; j <= high; j++) { sum2 += coin[j];//后半段和 } if (sum1 > sum2) { result = falsecoin(low + (high - low) / 2 + 1, high); //递推后半段 return result; } else if(sum1 < sum2) { result = falsecoin(low, low + (high - low) / 2); //递推前半段 return result; } } else //n是奇数 { for (int i = low;i<=low+(high-low)/2-1;i++) { sum1 += coin[i]; //中位数的前半段和 } for (int j = low + (high - low) / 2+1; j <= high; j++) { sum2 += coin[j]; //中位数的后半段和 } sum3 = coin[low + (high - low) / 2]; //中位数 if (sum1 > sum2) //前半段和大于后半段和 { result = falsecoin(low + (high - low) / 2 + 1, high);//递推后半段 return result; } else if (sum1 < sum2) //前半段和小于后半段和 { result = falsecoin(low, low + (high - low) / 2 - 1);//递推前半段 return result; } if (sum1 + sum3 == sum2 + sum3) //前半段和加中位数等于后半段和加中位数,所以中位数为目标寻找值 { result = low + (high - low) / 2+1; return result; } } } void fenzhi::showresult() { cout << "假币所在的位置:" << this->result << endl; } void text() { fenzhi fz; cout << "输入硬币的总数目:" << endl; cin >> fz.num; cout << "请输入硬币的真假(1真/0假):" << endl; for (int i = 0; i < fz.num; i++) { cin >> fz.coin[i]; } fz.falsecoin(0, fz.num - 1); fz.showresult(); } int main() { text(); }