分治算法解决硬币轻重问题

 

 

带子里面有若干个硬币 其中一枚是假币,并且假币和真币一模一样 肉眼很难分辨 目前只知道假币比真币的重量轻 请问如何分出真假币

import java.util.Scanner;




public class Demo04 {
  static final int MAXNUM=30;
  static int FalseCoin(int coin[],int low,int high)
  {
  int i,sum1,sum2,sum3;
  int re=0;
  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<=high;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;
  }
  }
  return re;
  }
  public static void main(String[] args) {
int [] coin =new int [MAXNUM];
int i,n;
int weizhi;
System.out.println("分治算法解决假币问题!");
System.out.println("请输入硬币总的个数:");
Scanner in =new Scanner(System.in);
n=in.nextInt();
System.out.println("请输入硬币的真假:");
for(i=0;i<n;i++)
{
coin[i]=in.nextInt();
}
weizhi=FalseCoin(coin, 0, n-1);
System.out.println("在上述"+MAXNUM+"个硬币中,第"+weizhi+"个硬币是假的!");
}



}

 

正硬币为2假硬币为1;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
硬币问题是一个经典的分治问题。假设你有 $n$ 枚硬币,其中有一枚是假的,比真的硬币。你可以使用天平来比较两堆硬币的重量。问你最少需要称多少次才能确定哪枚硬币是假的。 分治法是一种将问题分解成更小子问题的算法。在假硬币问题中,我们可以将硬币分成三组,然后比较其中两组,如果它们的重量相等,那么假硬币在第三组中;否则,假硬币在较的那组中。然后我们可以使用同样的方法继续在第三组中查找假硬币,递归执行下去,直到只剩下一枚硬币。 在每次比较中,我们总是能将硬币分成三组,因此每次比较的次数是固定的,即 $1$ 次。每次递归我们将问题规模缩小了 $3$ 倍,因此总的比较次数是 $T(n) = T(n/3) + 1$,解得 $T(n) = O(\log_3 n)$。 下面是一个使用分治法解决硬币问题的 Python 代码: ```python def find_fake_coin(coins): n = len(coins) if n == 1: return coins[0] elif n % 3 == 0: # 将硬币分成三组,分别称重 one_third = n // 3 left = coins[:one_third] middle = coins[one_third:2*one_third] right = coins[2*one_third:] # 比较左右两组的重量 if sum(left) == sum(right): # 假硬币在中间一组 return find_fake_coin(middle) elif sum(left) < sum(right): # 假硬币在左边一组 return find_fake_coin(left) else: # 假硬币在右边一组 return find_fake_coin(right) else: # 如果硬币不能被分成三组,我们可以在两端添加一些真硬币 # 使得硬币数变成 3 的倍数 k = n - (n // 3) * 3 coins += [1] * (3 - k) return find_fake_coin(coins) ``` 其中,`coins` 是一个列表,表示所有硬币的重量。函数返回假硬币的重量。如果硬币不能被分成三组,我们可以在两端添加一些真硬币,使得硬币数变成 3 的倍数。这里我们添加了重量为 $1$ 的真硬币,因为它不会影响结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值