• 蓝桥杯之递归算法基本框架


    有一根27厘米的细木杆,在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置上各有一只蚂蚁。
    木杆很细,只能同时通过一只蚂蚁。
    开始时,蚂蚁的头朝左还是朝右是任意的,它们只会朝前走或调头,但不会后退。
    当任意两只蚂蚁碰头时,两只蚂蚁会同时调头朝反方向走。假设蚂蚁们每秒钟可以走1厘米的距离。


    编写程序,求所有蚂蚁都离开木杆的最小时间和最大时间。


    思路:当两只蚂蚁相撞时,可以看成两只蚂蚁都没有掉头而直接向前爬行,最小时间即沿蚂蚁朝向到达杆外面的最短时间,最长时间即沿蚂蚁朝向到达杆外面的最长时间。

    代码:

    不用代码,直接画图就可以看出来...


    ---------------------------------------------------

    蚂蚁感冒

    长100厘米的细长直杆子上有n只蚂蚁。它们的头有的朝左,有的朝右。 
    每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒。
    当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。

    这些蚂蚁中,有1只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。
    请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。

    【数据格式】
        第一行输入一个整数n (1 < n < 50), 表示蚂蚁的总数。
        接着的一行是n个用空格分开的整数 Xi (-100 < Xi < 100), Xi的绝对值,表示蚂蚁离开杆子左边端点的距离。正值表示头朝右,负值表示头朝左,数据中不会出现0值,也不会出现两只蚂蚁占用同一位置。其中,第一个数据代表的蚂蚁感冒了。

        要求输出1个整数,表示最后感冒蚂蚁的数目。

    例如,输入:
    3
    5 -2 8
    程序应输出:
    1

    再例如,输入:
    5
    -10 8 -20 12 25
    程序应输出:
    3

    思路:
    由于存在感冒的蚂蚁,所以这道题不能使用上面的思路,观察发现,如果感冒的蚂蚁朝右,那么,所有在此蚂蚁后面且朝左的蚂蚁都会被感染,同时,在此蚂蚁左边且朝右的蚂蚁都会被感染,如果第一个感冒的蚂蚁朝左也是一个道理。


    代码:
    #include<cstdio>
    #include<cmath>


    int main(){
    int n,a,result=0,flag=1;
    scanf("%d",&n);
    while(n--){
    		int i;
    		scanf("%d",&i);
    		if(flag){
    			a=i;
    			flag=0;
    		}
    		if(a>0){
    			if(i>a&&i<0) result++;
    			if(i<a&&i>0) result++;
    		}
    		if(a<0){
    			if(i<a) result++;
    			if(i>0&&i<abs(a)) result++;
    		} 
    	}
    	printf("%d",result+1);
    } 
    ---------------------------------------------------
    搭积木

    小明最近喜欢搭数字积木。一共有10块积木,每个积木上有一个数字,0~9。

    搭积木规则:
    每个积木放到其它两个积木的上面,并且一定比下面的两个积木数字小。
    最后搭成4层的金字塔形,必须用完所有的积木。

    下面是两种合格的搭法:

       0
      1 2
     3 4 5
    6 7 8 9

       0
      3 1
     7 5 2
    9 8 6 4    

    请你计算这样的搭法一共有多少种?

    思路:

    代码:
    #include<cstdio>
    
    void show (int nums[]){
    	printf("   %d
    ",nums[0]);
    	printf("  %d %d
    ",nums[1],nums[2]);
    	printf(" %d %d %d
    ",nums[3],nums[4],nums[5]);
    	printf("%d %d %d %d
    ",nums[6],nums[7],nums[8],nums[9]);
    	printf("
    "); 
    }
    
    
    int N=0;
    
    
    void g(int a[],int k,int len){
    	if(k==len-1){
    		if(a[0]>a[1]||a[0]>a[2]||a[1]>a[3]||a[1]>a[4]||a[2]>a[4]||a[2]>a[5]||a[3]>a[6]||a[3]>a[7]||a[4]>a[7]||a[4]>a[8]||a[5]>a[8]||a[5]>a[9]){
    			return;
    		}else{
    			show(a);
    			N++;
    			return;
    		}
    	}	
    	
    	for(int i=k;i<len;i++){
    		int t=a[k];a[k]=a[i];a[i]=t;
    		g(a,k+1,len);
    		t=a[k];a[k]=a[i];a[i]=t;
    	}
    }
    
    
    int main(){
    	int nums[10]={0,1,2,3,4,5,6,7,8,9};
    	g(nums,0,10);
    	printf("%d
    ",N);
    } 
    
    ---------------------------------------------------
    [3.4 组合问题]
    问题: 5个中取3个,几种取法(不许用数学公式)
    f(m,n) = f(m-1,n) + f(m-1,n-1) 分为不取和要取

    代码:
    #include<cstdio>
    
    //组合问题
    int g(int m,int n){
    	
    	if(m==n) return 1;
    	if(n==0) return 1;
    	
    	return g(m-1,n)+g(m-1,n-1);
    }
    
    
    int main(){
    	
    	printf("%d",g(5,3));
    	
    }
    ---------------------------------------------------

    问题:串="ABC...." 中取3个,所有取法

    问题:"ABCDE" 中取3个,所有取法
    代码:
    #include<cstdio>
    
    int main(){
    	
    	for(char i='A';i<='E';i++){
    		for(char j=i+1;j<='E';j++){
    			for(char k=j+1;k<='E';k++){
    				printf("%c%c%c
    ",i,j,k);
    			}
    		}
    	}
    }
    问题:AAABBCCCCDD 中取3个,所有取法

    思路:建立数组,存储每个字母出现的次数,然后建立保存结果的数组(和原数组一样大),每次考虑一个数组位置,在这个位置,将该位置出现的次数从0到最大进行遍历,然后进行递归,考虑下个数组位置。

    代码:
    #include<cstdio>
    
    #define MIN(x,y) x>y?y:x
    
    void myprint(int re[],int len){	
    	for(int i=0;i<len;i++){
    		for(int j=0;j<re[i];j++){
    			printf("%c",i+'A');
    		}
    	}
    	printf("
    ");
    }
    
    
    void g(int chars[],int re[],int len,int k,int goal){	
    	if(k==len){
    		if(goal==0){
    			myprint(re,len);
    		} 
    		return;
    	}	
    	int min=MIN(chars[k],goal);
    	for(int i=0;i<=min;i++){
    		re[k]=i;
    		g(chars,re,len,k+1,goal-i);	
    	}	
    	re[k]=0;
    }
    
    
    int main(){
    	int chars[4]={3,2,4,2};
    	int re[4] = {0};
    	g(chars,re,4,0,3); 
    	
    	
    }
    ---------------------------------------------------
    代表团出访

    X星球要派出一个5人组成的观察团前往W星。
    其中:
    A国最多可以派出4人。
    B国最多可以派出2人。
    C国最多可以派出2人。
    D国最多可以派出1人。
    E国最多可以派出1人。
    F国最多可以派出3人。
    那么最终派往W星的观察团会有多少种国别的不同组合呢?

    思路:同上一题的思路,有重复元素的组合。

    代码:
    #include<cstdio>
    
    #define MIN(x,y) x>y?y:x
    int sum;
    
    void myprint(int re[],int len){	
    	for(int i=0;i<len;i++){
    		for(int j=0;j<re[i];j++){
    			printf("%c",i+'A');
    		}
    	}
    	printf("
    ");
    }
    
    void g(int chars[],int re[],int len,int k,int goal){	
    	if(k==len){
    		if(goal==0){
    			myprint(re,len);
    			sum++;
    		} 
    		return;
    	}	
    	int min=MIN(chars[k],goal);
    	for(int i=0;i<=min;i++){
    		re[k]=i;
    		g(chars,re,len,k+1,goal-i);	
    	}	
    	re[k]=0;
    }
    
    int main(){
    	int chars[6]={4,2,2,1,1,3};
    	int re[6] = {0};
    	g(chars,re,6,0,5); 
    	printf("%d",sum);
    	
    }
    ---------------------------------------------------

    枚举问题:排列枚举,组合枚举
    计数问题:排列计数,组合计数
    再加上难度:有重复元素

    ---------------------------------------------------


    作业题目


    A A 2 2 3 3 4 4, 一共4对扑克牌。请你把它们排成一行。
    要求:两个A中间有1张牌,两个2之间有2张牌,两个3之间有3张牌,两个4之间有4张牌。

    请填写出所有符合要求的排列中,字典序最小的那个。
    例如:22AA3344 比 A2A23344 字典序小。当然,它们都不是满足要求的答案。

    思路:将字符串以升序排列后调用next_permutation(str,str+len)进行全排列,当第一个符合条件的字符串出现时,结束循环。

    代码:
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    
    using namespace std;
    
    int main(){
    	
    	char str[]="223344AA";
    	int len=strlen(str);
    	
    	do
    	{
    		int a = strchr(str,'2')-str;
    		int b = strchr(str,'3')-str;
    		int c = strchr(str,'4')-str;
    		int d = strchr(str,'A')-str;
    		
    		if(str[d+2]=='A'&&str[c+5]=='4'&&str[b+4]=='3'&&str[a+3]=='2'){
    			printf("%s",str);
    			break;
    		}
    		
    	}while(next_permutation(str,str+len));
    	
    	return 0;
    }
    
    ---------------------------------------------------
    #include<algorithm>
    next_permutation(str,str+len);

  • 相关阅读:
    汇编--基础分析:数据段在内存中的存放及空间
    汇编语言(王爽)第六章检测点与实验5
    C语言经典例题100(22~40)
    C:数组小结(3)
    随机不重复的取数组元素,并赋值给div使用
    关于Apple设备私有的apple-touch-icon属性详解
    测试你女友是否跟你结婚插件的源码
    CSS子元素设置margin-top作用于父容器?
    hybrid app开发中:苹果移动设备实用Meta标签
    chromium 修改chromium的设置选项
  • 原文地址:https://www.cnblogs.com/sctb/p/11919662.html
Copyright © 2020-2023  润新知