有一根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;
}
—————————————————
#include<algorithm>
next_permutation(str,str+len);