【数据结构】分治算法求解假硬币问题

问题描述:

概念
分治算法的基本思想是将一个大的复杂的问题分解成多个小的、容易解决的问题,通过解决这些小问题进而解决这个大问题。

使用分治算法需要待求解问题能够简化为若干个小规模的相同的问题,通过逐步划分,达到一个易于求解的阶段,而直接进行求解,在程序中可以使用递归方法来进行求解。
哈哈,说起来很抽象,举个例子就好理解了。

一个袋子里有n个硬币,其中一枚是假币,并且假币和真币一模一样,仅凭肉眼无法区分,仅知道假币比真币轻一些,请问如何查找到假币?

分治算法:

我们可以这样做:

将这n个硬币分成两等份,然后放到天平的两端,则假币在较轻的那一端;

然后将较轻的那一端的硬币再分成2等份,然后再放到天平的两端进行比较,假币还是在较轻的那一段;

直到最后只剩下两个硬币了,分别放到天平的两端,轻的哪一个就是假币。

当然,最后也可能剩下3个硬币,我们可以将这3个硬币中任意拿出来一个,然后将剩下的两个放到天平的两端,如果天平是平的,则说明拿出来的那个硬币就是假币;

如果天平不是平的,则轻的那一端是假币。

代码实现:

#include<iostream>
#include<cstdio>
#include<cctype>
#define MAXNUM 30
using namespace std;

int FalseCoin(int coin[], int low, int high){
	int 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(int i=low; i<=low+(high-low)/2; i++){
			sum1=sum1+coin[i];
		}
		for(int 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(int i=low; i<=low+(high-low)/2-1; i++){
			sum1=sum1+coin[i];
		}
		for(int 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+sum3==sum2+sum3){
			re=low+(high-low)/2+1;
			return re;
		}
	}
}

int main(){
	int coin[MAXNUM];
	int i,n;
	int locate;
	cout<<"分治算法求解假硬币问题!\n";
	cout<<"请输入硬币总数目: ";
	cin>>n;
	cout<<"请输入硬币的真假:";
	for(i=0; i<n; i++){
		cin>>coin[i];
	}
	locate=FalseCoin(coin, 0, n-1);
	cout<<"在上述"<<n<<" 个硬币中,第"<<locate<<"个硬币是假的!"<<endl;
	return 0;
}

执行结果:

时间: 2024-08-08 17:58:21

【数据结构】分治算法求解假硬币问题的相关文章

分治算法求解序列最大子和问题

特别的,当序列所有整数均为负整数时,其最大子和为0. 1 #include <stdio.h> 2 3 int caluMaxSubSum(int *array, int left, int right); 4 5 int main() 6 { 7 int array[6] = {2, -2, 3, 1, -4, 2}; 8 int len_array = sizeof(array)/sizeof(array[0]); 9 int i = 0; 10 int subsum = caluMaxS

使用分治算法求解最大子数组问题

def MaxCrossSubarray(num,mid,low,high): leftsum=0 leftmax=-1000000 rightsum=0 rightmax=-1000000 for i in range(mid,low-1,-1): leftsum=leftsum+num[i] if leftsum>leftmax: leftmax=leftsum leftlow=i for j in range(mid+1,high+1): rightsum=rightsum+num[j]

分治算法初步

hdu1007 http://acm.hdu.edu.cn/showproblem.php?pid=1007 解题关键:分治算法求解,注意学习分治算法的写法 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<iostream> 7 #define inf 0x3f3f

《数据结构与算法分析 C语言描述》读书笔记——分治算法

书中用求解最大子序列和的方式介绍了分治算法(divide-and-conquer) 分治算法是一种相对快速的算法 运行时间为O(logN) 最大子序列和的问题如下: 给出一组整数 A1  A2 … AN 求∑jk=i Ak 若所有整数均为负 则最大子序列和为0 e.g. 输入-2, 11,-4, 13, -5, -2 输出20(A2到A4) 分治算法就如同字面描述的一样 先分再治 分 指的是将问题分为两部分几乎相同的子问题 进行递归求解 治 指的是将 分 的解通过简单的手段合并 得到最终解 对于

分治算法(二)

大家都知道选择排序和冒泡排序,这两个排序都是双重for循环,时间复杂度为O(n^2),显然效率都是比较低的,而运用分治思想的归并排序和快速排序会更高效一些. 1.归并排序 1)原理:假设初始序列含有n个记录,则可以看成是n个有序子序列,每个子序列的长度为1,然后两两归并,得到[n/2]([x]表示不小于x的最小整数)个长度为2或1的有序子序列:再两两归并,--,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法成为2路归并排序.(摘自<大话数据结构>) 可见其运用了典型的分治思想,①分

Pascal数据结构与算法

第一章 数据结构与算法的引入 1.1 数据结构的基本概念 一. 学习数据结构的意义 程序设计 = 数据结构 + 算法 目前,80%的待处理的数据具有“算法简单”(四则运算.检索.排序等),“对象复杂”(数据类型不同.数据量大.需要保存)等特点,故合理组织数据.选择较好的数据结构可为高效算法(时间少.占用空间小)提供理想的对象. 二.基本术语 1.数据(data): 是对客观事物的符号的表示,是所有能输入到计算机中并被计算机程序处理的符号的总称.(P1表1-1中,学号.姓名.性别.民族等列为字符型

数据结构与算法二

1.课程安排表: 1. 线性表 2. 字符串 3. 栈和队列 4.树 5.查找 6.排序 7.暴力枚举法 8.广度优先搜索 9.深度优先搜索 10.分治 11.贪心 12.动态规划 13.图 14.数学方法与常见模型 15.大整数运算 16. 基础功能 2.   编程技巧: 1.把较大的数组放在main 函数(全局变量)外,作为全局变量,这样可以防止栈溢出,因为栈的大小是有限制的.GCC (C编译器) 段错误 2.如果能够预估栈,队列的上限,则不要用stack,queue,使用数组来模拟,这样速

分治算法(一)

当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出.对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法.如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止.这就是分治策略的基本思想. 1.引例: 如果给你一个装有16枚硬币的袋子,其中有一枚是伪造的,并且那枚伪造硬币的重量和真硬币的重量不同.你能不能用最少

【转】数据结构与算法(下)

这篇文章是常见数据结构与算法整理总结的下篇,上一篇主要是对常见的数据结构进行集中总结,这篇主要是总结一些常见的算法相关内容,文章中如有错误,欢迎指出. 一.概述 二.查找算法 三.排序算法 四.其它算法 五.常见算法题 六.总结 一.概述 以前看到这样一句话,语言只是工具,算法才是程序设计的灵魂.的确,算法在计算机科学中的地位真的很重要,在很多大公司的笔试面试中,算法掌握程度的考察都占据了很大一部分.不管是为了面试还是自身编程能力的提升,花时间去研究常见的算法还是很有必要的.下面是自己对于算法这