算法设计与应用练习_递归

1.十进制转二进制
2.斐波那契数列
3.翻牌问题
4.打靶问题
5.八皇后问题

#include "stdio.h"
#include<time.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include "stdlib.h" 
//1.输入一个自然数(<90000),  分别用递归法和非递归法求其二进制表示.
//算法设计思想:num/2就是num的二进制序列当中除去最低位之外的部分,num%d表示输出num的二进制序列当中的最低位
/*递归算法*/  
void fun(int num)
 {
 	if(num==0)
 	return ;
 	else{
 		fun(num/2);
 		printf("%d", num%2);
	 } 
 }
int main()
{
	int num;
	printf("请输入一个自然数:"); 
	scanf("%d",&num);
	while(0>num||num>=90000) {
		printf("请重新输入:");	
		scanf("%d", &num);
	} 
	fun(num);	
	return 0;
 } 
 
/*非递归算法*/ 
int main() 
{
	int num;
	int i=0,j,b[32];   
	printf("请输入一个自然数:");   
	scanf("%d",&num);
	  while(num<0||num>=90000)
	  {
	  	printf("请重新输入:");
	  	scanf("%d",&num);
	  }              
	  while(num!=0)
	  {
	  	b[i++]=num%2;
	  	num=num/2;
	  }	
	  for(j=i-1;j>=0;j--)
	  	printf("%d",b[j]);
} 


//2.分别用递归法和非递归法求Fibonacci数列的前1000位,并比较计算时间的差异.
//函数FiboD(num)的特点是,如果n不是递归出口,那么一个规模是n的Fbio函数就可以转化为两个规模更小的Fbio函数的和,一个是Fbio(n-1),一个是Fbio(n-2)。如果这两个函数仍然没有到达递归终点,仍需要继续递归分解。 
/*递归算法*/ 
int FiboD(int n)
{
	int val;
	if(n==1||n==2)
	return 1;
	val = FiboD(n-1)+FiboD(n-2);
	return val;
}
/*非递归算法*/
int FiboF(int n){
	int a = 1, b = 1;
    if(n==1 || n==2) return 1;
    for(int i=3; i<=n; i++){
    int tmp = b;
    b = a + b;
    a = tmp;
}
    return b;
}
int main()
{   
    int num=50;
    /* FbioD递归持续的时间*/  
   clock_t start1, finish1;  
   double  duration1;   
   printf("FiboD递归的时间是:");  
   start1 = clock();  
   FiboD(num);  
   finish1 = clock();  
   duration1 = (double)(finish1 - start1) / CLOCKS_PER_SEC;  
   printf( "%f seconds\n", duration1 ); 
   /* FiboD非递归测持续的时间*/  
   clock_t start2, finish2;  
   double  duration2;  
   printf("FiboF非递归的时间是:");  
   start2 = clock();  
   FiboF(num);  
   finish2 = clock();  
   duration2 = (double)(finish2 - start2) / CLOCKS_PER_SEC;  
   printf( "%f seconds\n", duration2 ); 
   system("pause"); 	
}
/*3.用递归算法完成如下问题:有52张牌,使它们全部正面朝上,第一轮是从第2张开始,凡是2的倍数位置上的牌翻成正面朝下;
/*第二轮从第3张牌开始,凡是3的倍数位置上的牌,正面朝上的翻成正面朝下,正面朝下的翻成正面朝上;第三轮从第4张牌开始,凡是4的
倍数位置上的牌按上面相同规则翻转,以此类推,直到第一张要翻的牌超过52为止。统计最后有几张牌正面朝上,以及它们的位置号.*/ 

using namespace std;
bool card[100]; 
void turn(int x)
{
    if(x>52)  return;
    for(int i=x;i<=52;i+=x)
{
    card[i]=!card[i];
}
    turn(x+1);
}
int main()
{
    memset(card,1,sizeof(card));
    turn(2);
for(int i=1;i<=52;i++)
{
    if(card[i])
    cout<<i<<endl;
}
return 0;
}
/*4.一个射击运动员打靶,靶一共有10环,连开6枪打中45环的可能性有多少种? (每一枪最少是0环,最多是10环)*/
using namespace std;
int sum;
int store[6];
void compute(int score,int num)
{
    //score<0即总的成绩超过45环,或者剩下要打的靶的成绩大于10环乘以剩下要打的靶数
    //这两种情况下不用在大了
    if(score<0||score>(num+1)*10)
        return;
    //如果满足条件并且打到最后一次
    if(num==0)
    {
        store[num]=score;
        sum++;
        return;
    }
    for(int i=0;i<=10;++i)
    {
        //顺序倒了,store[6]是第一次打的,。。。store[0]是最后一次打的
        store[num]=i;
        compute(score-i,num-1);
    }
}
 
int main()
{
    compute(45,5);
    cout<<"总数"<<sum<<endl;
    return 0;
}
 
 


 //5.在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,输出所有摆法。
//编程思想:有8个元素的数组记录已经摆放的棋子摆在什么位置,当要放置一个新的棋子时,只需要判断它与已经放置的棋子之间是否冲突就行了。
/*从棋盘的第一行开始,从第一个位置开始,依次判断当前位置是否能够放置皇后,判断的依据为:同该行之前的所有行中皇后的所在位置进行比较,如果在同一列,或者在同一条斜线上(斜线有两条,为正方形的两个对角线),都不符合要求,继续检验后序的位置。
如果该行所有位置都不符合要求,则回溯到前一行,改变皇后的位置,继续试探。
如果试探到最后一行,所有皇后摆放完毕,则直接打印出 8*8 的棋盘。最后一定要记得将棋盘恢复原样,避免影响下一次摆放。*/

int Queenes[8]={0},Counts=0;
int Check(int line,int list){
    //遍历该行之前的所有行
    for (int index=0; index<line; index++) {
        //挨个取出前面行中皇后所在位置的列坐标
        int data=Queenes[index];
        //如果在同一列,该位置不能放
        if (list==data) {
            return 0;
        }
        //如果当前位置的斜上方有皇后,在一条斜线上,也不行
        if ((index+data)==(line+list)) {
            return 0;
        }
        //如果当前位置的斜下方有皇后,在一条斜线上,也不行
        if ((index-data)==(line-list)) {
            return 0;
        }
    }
    //如果以上情况都不是,当前位置就可以放皇后
    return 1;
}
//输出语句
void print()
{
    for (int line = 0; line < 8; line++)
    {
        int list;
        for (list = 0; list < Queenes[line]; list++)
            printf("0");
        printf("*");
        for (list = Queenes[line] + 1; list < 8; list++){
            printf("0");
        }
        printf("\n");
    }
    printf("================\n");
}
void eight_queen(int line){
    //在数组中为0-7列
    for (int list=0; list<8; list++) {
        //对于固定的行列,检查是否和之前的皇后位置冲突
        if (Check(line, list)) {
            //不冲突,以行为下标的数组位置记录列数
            Queenes[line]=list;
            //如果最后一样也不冲突,证明为一个正确的摆法
            if (line==7) {
                //统计摆法的Counts加1
                Counts++;
                //输出这个摆法
                print();
                //每次成功,都要将数组重归为0
                Queenes[line]=0;
                return;
            }
            //继续判断下一样皇后的摆法,递归
            eight_queen(line+1);
            //不管成功失败,该位置都要重新归0,以便重复使用。
            Queenes[line]=0;
        }
    }
}
int main() {
    //调用回溯函数,参数0表示从棋盘的第一行开始判断
    eight_queen(0);
    printf("摆放的方式有%d种",Counts);
    return 0;
}
发布了13 篇原创文章 · 获赞 5 · 访问量 5237

猜你喜欢

转载自blog.csdn.net/lujiebin/article/details/102567491