【无标题】

文章通过一系列问题探讨了计算机编程中的算法设计。首先,讨论了蚂蚁在细木杆上行走并可能相撞的情况,求解所有蚂蚁离开木杆的最小和最大时间。其次,引入感冒传染因素,计算在蚂蚁相撞时感冒传播的范围。接着,文章转向积木搭建问题,寻找符合特定条件的积木排列方式。最后,涉及组合计数问题,如从特定序列中选取元素的所有组合,并给出了排列枚举的例子。
摘要由CSDN通过智能技术生成

有一根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\n",nums[0]); printf(" %d %d\n",nums[1],nums[2]); printf(" %d %d %d\n",nums[3],nums[4],nums[5]); printf("%d %d %d %d\n",nums[6],nums[7],nums[8],nums[9]); printf("\n"); } 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",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\n",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("\n"); } 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("\n"); } 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; }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值