伪币问题

来源:互联网 发布:de castljau算法 编辑:程序博客网 时间:2024/05/21 15:45

因为本题使用了分治法,我先介绍一下分治法的思想吧

分治法的基本思想就是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同.递归的解这些子问题,然后将各个子问题的解合并得到原问题的解.

(其实就是把一个大问题不断的分小,然后一个个解决啦)

题目:设有16枚硬币,其中有一枚伪币,真币重量都一样,伪币质量比真币轻,现在要找出那枚伪币

分析:16枚硬币,我们可以分两组,算出质量小的一边,再继续分下去,直到最后找出该伪币,所以我们可以使用分治法来求

以下是代码

// 使用的库定义 ...#include < stdio.h >#include < stdlib.h >#include < time.h >#define ARRAY_SIZE 16#define TRUE       1#define FALSE      0int CallTimes = 0;int t;// 生成包含 'N' 个硬币重量的数组( 含 1 枚伪币 ), 并返回伪币位置 ...int CreateRandomCoinWeightArray( int *p, int N ){  int i, kt;  int TrueCoinWeight, FakeCoinWeight;  int IsStop;  // 生成随机数种子 ...  srand( ( unsigned )time( NULL ) );  // 生成随机真币重量值( 在 50 至 100 之间 ) ...  TrueCoinWeight = 50 + rand( ) % ( 100 - 50 );  // 生成随机伪币位置( 在 0 ~ N-1 之间 ) ...  kt = rand( ) % N;  // 设置真币重量 ...  for( i = 0; i < N; i++ )    if ( i != kt )      *( p + i ) = TrueCoinWeight;  // 生成 1 个比真币略轻的伪币重量值 ...  IsStop = FALSE;  while( !IsStop )  {    FakeCoinWeight = 50 + rand( ) % ( 100 - 50 );// 设置满足条件的伪币重量值 ...if ( ( TrueCoinWeight > FakeCoinWeight ) && ( TrueCoinWeight - FakeCoinWeight <= 5 ) ){      IsStop = TRUE;  *( p + kt ) = FakeCoinWeight;}  }  // 返回伪币位置 ...  return kt;}// 计算数组中硬币重量和 ...int CalcCoinTotalWeight( int ArrayData[], int kb, int ke ){  int i, TotalWeight = 0;   for( i = kb; i <= ke; i++ )    TotalWeight += ArrayData[ i ];  return TotalWeight;}// 采用分治法找到伪币( 假定伪币一定存在且只有 1 枚 ) ...// kb - (子)数组左边界( begin )// ke - (子)数组右边界( end )int FindFakeCoin( int ArrayData[], int kb, int ke )//kb前下标,ke后下标{  int LWeight, RWeight;  CallTimes++;  printf( "< 第 %d 次查找 > \n", CallTimes );//采用分治法来求解  LWeight=CalcCoinTotalWeight(ArrayData,kb,(kb+ke)/2);  RWeight=CalcCoinTotalWeight(ArrayData,(kb+ke+1)/2,ke);   if(LWeight<RWeight){     ke=(kb+ke)/2;     if(kb==ke) { t=(kb+ke)/2;  return t; } FindFakeCoin(ArrayData,kb,ke); }  else if(LWeight>RWeight){ kb=(kb+ke+1)/2; if(kb==ke) { t=(kb+ke)/2;  return t; } FindFakeCoin(ArrayData,kb,ke);  }  return t;}// ####################################################################### ////                                                                         // //                           下面是主程序开始                              // //                                                                         // // ####################################################################### //void main( void ){  int ArrayData[ ARRAY_SIZE ];  int i, k, FakeCoinPos;  // 生成包含 'N' 个硬币重量的数组( 含 1 枚伪币 ), 并返回伪币位置 ...  k = CreateRandomCoinWeightArray( ArrayData, ARRAY_SIZE );  // 输出随机数组内容 ...  printf( "< 生成的硬币重量数组值为( 含 1 枚伪币 ) > : \n" );  for( i = 0; i < ARRAY_SIZE; i++ )    printf( "%d\n", ArrayData[ i ] );  printf( "\n" );  printf( "< 第 %d 枚为伪币 > \n", ( k + 1 ) );  printf( "\n" );  // 采用分治法找到伪币位置 ...  FakeCoinPos = FindFakeCoin( ArrayData, 0, ARRAY_SIZE - 1 );  printf( "< 找到第 %d 枚为伪币 > \n", ( FakeCoinPos + 1 ) );  printf( "\n" );  // 等待用户输入任意一键返回 ...  system( "PAUSE" );}
其中核心代码为

if(LWeight<RWeight){     ke=(kb+ke)/2;     if(kb==ke) { t=(kb+ke)/2;  return t; } FindFakeCoin(ArrayData,kb,ke); }  else if(LWeight>RWeight){ kb=(kb+ke+1)/2; if(kb==ke) { t=(kb+ke)/2;  return t; } FindFakeCoin(ArrayData,kb,ke);  }

我们计算出左边质量和右边质量,kb为左边边界的下标,ke为右边边界的下标,如果左边质量小,则伪币在左边,我们就把右边的边界往中间移,反之就把左边边界往中间移,一直进行,知道最后左边边界和右边边界相等,说明这是只剩下一个硬币,而这枚硬币正好是我们要找的伪币.

0 0