通过一个例子来介绍分治算法的应用。一个袋子里有30枚银币,其中一枚银币为假,并且假银币和真银币一模一样,肉眼很难分辨,目前只知道假银币比真银币重量轻一点。请问如何找出假银币?
首先来分析一下寻找假银币的问题,可以采用递归分治的思想来求解这个问题,操作如下:
(1)首先为每个银币编号,然后将所有的银币等分为两份,放在天平的两边。这样就将区分30个银币的问题变为区分两堆银币的问题。
(2)因为假银币的重量较轻,因此天平较轻的一侧一定包含假银币。
(3)再将较轻的一侧中的硬银币等分为两份,重复上述做法。
(4)直到剩下两枚银币,便可用天平直接找出假银币。
int FalseCoin(int *coin,int low,int high)
{
int i,sum1,sum2,sum3;//定义三个变量sum1为前半段和,sum2为后半段和,sum3为奇数中间的数
int re;
sum1=sum2=sum3=0;
if(low+1=high)//只有两个数
{
if(coin[low]<coin[high])
{
re=low+1;
return re;//返回假银币的位置
}
else
{
re=high+1;
return re;
}
}
if((high-low+1)%2==0)//偶数个银币
{
for(i=low;i<=low+(high-low)/2;i++)
{
sum1=sum1+coin[i];//前半段之和
}
for(i=low+(high-low)/2+1;i<=high;i++)
{
sum2=sum2+coin[i];//后半段之和
}
if(sum1>sum2)
{
re=FalseCoin(coin,low+(high-low)/2+1,high);
return re;
}
else if(sum1<sum2)
{
re=FalseCoin(coin,low,low+(high-low)/2);
return re;
}
else
{
}
}
else//奇数个银币
{
for(i=low;i<=low+(high-low)/2-1;i++)
{
sum1=sum1+coin[i];//前半段和
}
for(i=low+(high-low)/2+1;i++)
{
sum2=sum2+coin[i];//后半段和
}
sum3=coin[low+(high-low)/2];//奇数中间的那个数字
if(sum1>sum2)
{
re=FalseCoin(coin,low+(high-low)/2+1,high);
return re;
}
else if(sum1<sum2)
{
re=FalseCoin(coin,low,low+(high-low)/2-1);
return re;
}
else
{
}
if(sum1+sum3==sum2+sum3)//奇数中间的为假币
{
re=low+(high-low)/2+1;
return re;
}
}
}
来源:CSDN
作者:灿烂的人生
链接:https://blog.csdn.net/qq_43404969/article/details/104333433