初识算法

在实际应用中,不同问题的解题思路往往也不尽相同。如果找不到一个合适的思路,那么求解过程可能就会变得冗长复杂,甚至最后无法求得正确的结果,而当选择了合适的思路,我们便能轻易找到解题的关键并正确而且高效地解决问题。由此可见,思路(也就是算法)的作用至关重要。 根据实际上遇到的问题,算法可以分为以下几种:

1.穷举算法思想

依赖于计算机强大的计算功能来穷尽(即枚举)每一种可能发生的情况,从而达到求解的目的。该算法思想简单,但效率不高,但适用于一些没有明显规律的场合。 例子: 例:鸡兔同笼问题 今有鸡兔同笼 上有三十五头 下有九十四足 问鸡兔各几何 代码:

#include <iostream>
using namespace std;
int main()
{
	int res=0,rabbit,chicken;
	int head=35,foot=94;
	for(int i=0;i<=head;i++)
	{
		int j=head-i;
		if(i*4+j*2==foot)
		{
			rabbit=i;
			chicken=j;
		}
	}
	cout<<"共有"<<rabbit<<"只兔子"<<endl
	<<chicken<<"只鸡"<<endl; 
	return 0;
}

2.递推算法思想

递推算法是一种理性思维模式的代表,根据已有的数据以及关系,逐步推导而得到结果。该算法需要我们了解问题与答案之间的逻辑关系。在许多数学问题中,都有明确的计算公式可以遵循,因此常常使用递推算法来实现。 例子: 斐波那契列:

《初识算法》

代码:

#include <iostream>
using namespace std;

int fabonaci(int n); 
int main()
{
	int res=0;
	int n;
	cout<<"请先输入n"<<endl;
	cin>>time;
	res=fabonaci(time);
	cout<<res<<endl; 
	return 0;
}

int fabonaci(int n)
{
	int t1,t2;
	if(n==1||n==2)
	{
		return 1;
	}
	else
	{
		t1=fabonaci(n-1);
		t2=fabonaci(n-2);
		return t1+t2;
	}
}

3.递归算法思想

递归算法是一种非常常用的算法思想。使用递归算法,往往可以起到简化代码,提高程序可读性的效果。该算法就是在程序的执行过程中不断调用自身来达到求解的目的。使用该算法求解,要求求解的问题可以分解成相同问题的一个子问题。这样,经过多次递归调用,才能得到问题的解。当然,该算法思想也存在着许多问题,递归的形式比非递归的运行速度要慢一些,这是因为附加的函数调用延长了时间(计算机需要执行一系列的压栈与出栈操作)。如果递归层次太深,还可能导致堆栈溢出。典型的使用递归算法思想的例子有汉诺塔问题等 例子: 计算N的阶乘

#include <iostream>
using namespace std;

long fact(int n);

int main()
{
	int i,res=0;
	cout<<"请输入要求阶乘的一个整数"<<endl;
	cin>>i;
	res=fact(i);
	cout<<i<<"的阶乘为"<<res<<endl;
	return 0;
}

long fact(int n)
{
	if(n<=1)
	{
		return 1;
	}
	else
	{
		return n*fact(n-1);
	}
}

4.分冶算法思想

分冶算法一种化繁为简的算法思想,该算法往往应用于计算步骤比较复杂的问题,且求解问题可以划分为若干个规模较小,求解简单的子问题。快速排序,合并排序算法均体现了这种算法思想。 例子: 一个袋子有30枚银币,其中一枚是假的,并且假银币与真银币一模一样, 肉眼很难区分,目前只知道假银币比真银币的重量轻一点 试问如何找出假银币? 代码如下:

#include <iostream>
using namespace std;

#define MAXSIZE 30
int selectFalse(int coins[],int low,int high);

int main() {
	int coins[MAXSIZE];
	int n;
	int pos;
	cout<<"请输入银币总的个数"<<endl;
	cin>>n;
	cout<<"请输入各个银币的重量"<<endl;
	for(int i=0;i<n;i++){
		cin>>coins[i];
	}
	pos=selectFalse(coins,0,n-1
	);
	cout<<"假的银币在第"<<pos<<"个"<<endl;
	return 0;
}

int selectFalse(int coins[],int low,int high) { //coins数组存储各个银币重量,low为寻找的起始银币编号,high为寻找的结束银币编号
	int sum1,sum2,sum3;
	sum1=sum2=sum3=0;
	int res;
	if(low+1==high) {
		if(coins[low]<coins[high]) { //假银币位于low位置
			res=low+1;
		} else if(coins[low]>coins[high]) {
			res=high+1;
		}
	}

	if((high-low+1)%2==0) { //n为偶数
		for(int i=low; i<=low+(high-low)/2; i++) {
			sum1=sum1+coins[i];
		}

		for(int j=low+(high-low)/2+1; j<=high; j++) {
			sum2+=coins[j];
		}

		if(sum1>sum2) {
			res=selectFalse(coins,low+(high-low)/2+1,high);
			return res;
		}

		else if(sum1<sum2) {
			res=selectFalse(coins,low,low+(high-low)/2+1);
			return res;
		} else {
			return -1;
		}
	} else {
		for(int i=low; i<=low+(high-low)/2-1; i++) {
			sum1+=coins[i];
		}
		for(int j=low+(high-low)/2+1; j<=high; j++) {
			sum2+=coins[j];
		}
		sum3=coins[low+(high-low)/2];
		if(sum1>sum2){
			res=selectFalse(coins,low+(high-low)/2+1,high);
			return res;
		} else if(sum1<sum2){
			res=selectFalse(coins,low,low+(high-low)/2-1);
			return res;
		} else if(sum1+sum3==sum1+sum3) {
			res=low+(high-low)/2+1;
			return res;
		}
	}
}

5.概率算法思想

概率算法是依照概率统计的思路来求解问题的算法,它往往不能得到问题的精确解,但却在数值计算领域得到了广泛的应用。 概率算法执行的基本过程: (1)将问题转化为相应的几何图形S,S的面积是容易计算的,问题的结果往往对应几何图形的某一部分S1的面积 (2)向几何图形中随机撒点。 (3)统计几何图形S和S1中的点数,根据S面积和S1面积的关系以及各图形中的点数来计算得到结果 (4)判断上述结果是否在需要的精度之内,如果未达到精度则执行步骤(2)。如果达到精度,则输出近似结果

概率算法大致可以分为如下4类 1)数值概率算法: 数值概率算法常用于数值问题的求解。这类算法所得到的往往是近似解。而且近似解的精度随计算时间的增加不断提高。在许多情况下,要计算出问题的精确解是不可能或没有必要的,因此用数值概率算法可得到相当满意的解。 2)蒙特卡罗算法: 蒙特卡洛算法用于求问题的准确解。蒙特卡洛算法1945年由冯诺依曼行核武模拟提出的。它是以概率和统计的理论与方法为基础的一种数值计算方法,它是双重近似:一是用概率模型模拟近似的数值计算,二是用伪随机数模拟真正的随机变量的样本。 3)拉斯维加斯算法: 拉斯拉维加算法不会得到不正确的解,一旦用拉斯维加斯算法找到一个解,那么这个解肯定是正确的。但是有时候用拉斯拉维加算法可能找不到解。与蒙特卡罗算法类似。拉斯拉维加算法得到正确解的概率随着它用的计算时间的增加而提高。对于所求解问题的任一实例,用同一拉斯拉维加算法反复对该实例求解足够多次,可使求解失效的概率任意小。 4)舍伍德算法: 舍伍德算法总能求得问题的一个解,且所求得的解总是正确的。当一个确定性算法在最坏情况下的计算复杂性与其在平均情况下的计算复杂性有较大差别时,可以在这个确定算法中引入随机性将它改造成一个舍伍德算法,消除或减少问题的好坏实例间的这种差别。舍伍德算法精髓不是避免算法的最坏情况行为,而是设法消除这种最坏行为与特定实例之间的关联性

例子:利用蒙特卡罗算法计算圆周率PI

#include <iostream>
using namespace std;
#include <stdlib.h>
#include <time.h>

double MontePI(int n);

int main()
{
	int n;
	cout<<"请输入撒点个数"<<endl;
	cin>>n;
	cout<<"PI="<<MontePI(n)<<endl;
	return 0;
}

double MontePI(int n)
{
	double PI;
	double x,y;
	int sum=0;
	srand(time(NULL));
	for(int i=0;i<n;i++){
		x=(double)rand()/RAND_MAX;
		y=(double)rand()/RAND_MAX;
		if((x*x+y*y)<=1)//若在阴影区域
		{
			sum++;
		} 
	}
	PI=4.0*sum/n;
	return PI;
}
点赞