c_算法_枚举、递推、递归、迭代、分治

1、枚举:本质就是从所有候选答案中去搜索正确的解,使用该算法需要满足两个条件:(1)可预先确定候选答案的数量;(2)候选答案的范围在求解之前必须有一个确定的集


#include<stdio.h>
#include<windows.h>
/*
*枚举法:实现给出任意五个数和结果,利用加减乘除使等式成立
*考虑1:优先级
*考虑2:除法右边不能为0;
*/
int judge(int num[],int len,int result)
{
 int op[4] = { '+', '-', '*', '/' };
 int exp[4];
 int count = 0;
 for (exp[0] = 0; exp[0] < 4; exp[0]++){//第一个空位的操作符判断
  if (exp[0] == 3 && num[1] == 0){//当操作数是/时右边不能为0
   return 0;
  }
  for (exp[1] = 0; exp[1] < 4; exp[1]++){//第二个空位的操作符判断
   if (exp[1] == 3 && num[2] == 0){
    return 0;
   }
   for (exp[2] = 0; exp[2] < 4; exp[2]++){//第三个空位的操作符判断
    if (exp[2] == 3 && num[3] == 0){
     return 0;
    }
    for (exp[3] = 0; exp[3] < 4; exp[3]++){//第四个空位的操作符判断
     if (exp[3] == 3 && num[4] == 0){
      return 0;
     }
     int flag = 1;
     int sum = 0;
     int index = num[0];
     for (int j = 0; j < 4; j++){
      switch (op[exp[j]]){
      case '+':
       sum = sum + flag*index;
       index = num[j + 1];
       flag = 1;
       break;
      case '-':
       sum = sum + flag*index;
       index = num[j + 1];
       flag = -1;
       break;
      case '*':
       index = index*num[j + 1];//优先级执行
       break;
      case '/':
       index = index/num[j + 1];
       break;
      }
     }
     
     if ((sum + flag*index) == result){//已执行完乘和除
      count++;
      for (int j = 0; j < 4; j++){
       printf("%d%c", num[j], op[exp[j]]);
      }
      printf("%d=%d\n", num[4], result);
     }
    }
   }
  }
 }
 if (count == 0){
  printf("无匹配结果!\n");
 }
 return 0;
}
int main()
{
 printf("请输入5个操作数:");
 int num[5];
 int i = 0;
 for (; i < 5; i++){
  scanf_s("%d", &num[i]);
 }
 printf("请输入结果:");
 int result;
 scanf_s("%d", &result);
 judge(num, 5, result);
 system("pause");
 return 0;
}
1、递推和递归
    相对于递归算法,递推算法免除了数据进出栈(递归运算运行时的开销是它的一大缺点:参数必须压到堆栈中,为局部变量分配内存空间的过程,也就是说,不需要函数不断的向边界值靠拢,而直接从边界出发,直到求出函数值。
2、递推:给定一个数的序列H0,H1,…,Hn,…若存在整数n0,使当n>n0时,可以用等号(或大于号、小于号)将Hn与其前面的某些项Hi(0<i<n)联系起来,这样的式子就叫做递推关系。
3、递归:就是一种直接或间接调用自己的算法,它所需要的两个特性:①存在限制条件,当符合这个条件时递归便不再继续;②每次递归调用之后越来越接近这个限制条件。
4、递归与迭代
    由于递归的开销太大与浪费,当递归是尾部递归(即为递归调用是函数的最后一项任务)时,可以很容易的转为迭代算法相对有效的进行运算。
5、迭代(辗转)数值分析中通过从一个初始估计出发寻找一系列近似解来解决问题(一般是解方程或者方程组)的过程,为实现这一过程所使用的方法统称为迭代法,它 用计算机解决问题的一种基本方法,它利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)进行重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值。

#include<stdio.h>
#include<Windows.h>

#pragma warning(disable:4996)

//斐波拉契数列(兔子数列):每个数都等于它前两个数之和
//递推算法:求斐波拉契数列的某一项
int derivate(int fib[], int n)
{
	fib[0] = 1;
	fib[1] = 1;
	for (int i = 2; i < n; i++){
		fib[i] = fib[i - 1] + fib[i - 2];
	}
	return fib[n-1];	
}

//递归算法:求斐波拉契数列的某一项
//不建议用开销空间大且浪费空间严重,效率低
int recurse(int n){
	if (n <= 2){
		return 1;
	}
	return recurse(n - 1) + recurse(n - 2);//尾部递归
}

//迭代算法:求斐波拉契数列的某一项
//最佳:相对于递推,定义局部变量少,开销空间小,效率高
int iterate(int n)
{
	int first = 1;
	int before = 1;
	int pre = 0;
	int i = 1;
	while (i <= n - 2){
		pre = before + first;
		first = before;
		before = pre;
		i++;
	}
	return pre;
}

int main()
{
	int n;
	scanf("%d", &n);
	int *fib;
	fib = (int*)malloc(n*sizeof(int));
	printf("%d\n", derivate(fib, n));
	printf("%d\n", recurse(n));
	printf("%d\n", iterate(n));
	system("pause");
	return 0;
}
1、分治算法:
        基本思想:将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同
        解题的一般步骤:
(1)分解,将要解决的问题划分成若干规模较小的同类问题;
2)求解,当子问题划分得足够小时,用较简单的方法解决;
(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。
#include<stdio.h>
#include<Windows.h>

#pragma warning(disable:4996)

#define N 64
int arr[N+1][N+1] = { 0 };
//分治算法:安排比赛选手的比赛日程
//思路:对于参赛选手为2的次方情况,将四个分为一组进行安排
void divideAndSolve(int k, int n)
{
	if (n == 2){
		arr[k][1] = k;//参赛选手
		arr[k][2] = k + 1;//对战选手
		arr[k + 1][1] = k + 1;
		arr[k + 1][2] = k;
	}
	else{
		divideAndSolve(k, n / 2);//1,2
		divideAndSolve(k + n / 2, n / 2);//3,4
		for (int i = k; i < k + n / 2; i++){
			for (int j = n / 2 + 1; j <= n; j++){
				arr[i][j] = arr[i + n / 2][j - n / 2];
			}
		}
		for (int i = k + n / 2; i <= k + n; i++){
			for (int j = n / 2 + 1; j <= n; j++){
				arr[i][j] = arr[i - n / 2][j - n / 2];
			}
		}
	}
}


int main()
{
	int n;
	scanf("%d", &n);
	divideAndSolve(1, n);
	printf("编号\t");
	for (int i = 1; i < n; i++){
		printf("第%d天\t", i);
	}
	printf("\n");
	for (int i = 1; i <= n; i++){
		for (int j = 1; j <= n; j++){
			printf("%d\t", arr[i][j]);
		}
		printf("\n");
	}
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/tec_1535/article/details/79919059