【C/C++】C语言复习笔记-17种小算法-解决实际问题
判断日期为一年中的第几天(考虑闰年)
1 /* 2 * 计算该日在本年中是第几天,注意闰年问题 3 * 以3月5日为例,应该先把前两个月的加起来,然后再加上5天即本年的第几天 4 * 特殊情况,闰年且输入月份大于3时需考虑多加一天 5 */ 6 7 /* 8 *@author: 成鹏致远 9 *@net: http://infodown.tap.cn 10 */ 11 12 #include <stdio.h> 13 #include <stdbool.h> 14 15 struct year_mon_day 16 { 17 int year; 18 int mon; 19 int day; 20 }; 21 22 int main() 23 { 24 int i; 25 int sum;//总天数 26 bool flag = false;//闰年标志 27 struct year_mon_day ymd; 28 29 printf("Pls input year,mon day:"); 30 scanf("%d%d%d",&ymd.year,&ymd.mon,&ymd.day); 31 32 switch(ymd.mon) 33 { 34 case 1: 35 sum = 0; 36 break; 37 case 2: 38 sum = 31; 39 break; 40 case 3: 41 sum = 59; 42 break; 43 case 4: 44 sum = 90; 45 break; 46 case 5: 47 sum = 120; 48 break; 49 case 6: 50 sum = 151; 51 break; 52 case 7: 53 sum = 181; 54 break; 55 case 8: 56 sum = 212; 57 break; 58 case 9: 59 sum = 243; 60 break; 61 case 10: 62 sum = 173; 63 break; 64 case 11: 65 sum = 304; 66 break; 67 case 12: 68 sum = 334; 69 break; 70 default: 71 printf("data error \n"); 72 return 1; 73 } 74 sum += ymd.day; 75 76 if(ymd.year/100 || (ymd.year%4 && ymd.year%100 != 0)) 77 { 78 flag = true; 79 } 80 81 if(1==flag && ymd.mon>2) 82 { 83 sum++; 84 } 85 86 printf("%d年%d月%d日 是%d年的第%d天 \n",ymd.year,ymd.mon,ymd.day,ymd.year,sum); 87 88 return 0; 89 }
十进制转十六进制
1 /*函数实现输入一个十进制数,输出对应的十六进制数*/ 2 /* 3 *@author: 成鹏致远 4 *@net: http://infodown.tap.cn 5 */ 6 7 #include <stdio.h> 8 #include <stdbool.h> 9 #define LIM 32 10 11 int main(void) 12 { 13 int decimal; 14 bool negative = false; 15 printf("pls input the integer to convert:\n"); 16 17 if(!scanf("%d", &decimal)) 18 { 19 printf("we need an integer, Bye-bye!\n"); 20 return -1; 21 } 22 if(decimal < 0) 23 { 24 negative = true; 25 decimal *= -1; 26 } 27 28 int i, num[LIM]; 29 for(i=0; i<LIM && decimal!=0; i++) 30 { 31 num[i] = decimal%16; 32 decimal /= 16; 33 } 34 35 int j; 36 if(negative) 37 printf("answer: -0x"); 38 else 39 printf("answer: 0x"); 40 41 for(j=i; j>0; j--){ 42 switch(num[j-1]){ 43 case 10: 44 printf("a"); 45 break; 46 case 11: 47 printf("b"); 48 break; 49 case 12: 50 printf("c"); 51 break; 52 case 13: 53 printf("d"); 54 break; 55 case 14: 56 printf("e"); 57 break; 58 case 15: 59 printf("f"); 60 break; 61 default: 62 printf("%d", num[j-1]); 63 break; 64 } //switch 65 } //for 66 printf("\n"); 67 68 return 0; 69 }
打印指定的字母金字塔(技巧)
1 /* 2 * 产生一个字母金字塔图案 3 * author:成鹏致远 4 * net:infodown.tap.cn 5 */ 6 7 #include <stdio.h> 8 9 void PintLetterPic(char); //打印出金字搭字母图案 10 11 int main() 12 { 13 char letter; 14 15 printf("Please input a capital letter:"); 16 scanf("%c",&letter); 17 18 PintLetterPic(letter); 19 20 return 0; 21 } 22 23 void PintLetterPic(char c) //打印出金字搭字母图案 24 { 25 int len = c - 'A'+1; //注意这里需要+1!!! 26 int len2 = 2*len; 27 char tem[100][200]; 28 int i,j; 29 char tempchar = 'A'; 30 31 for(i=0; i<100; i++) //初始化二维数组 32 { 33 for(j=0; j<200; j++) 34 { 35 tem[i][j] = ' '; 36 } 37 } 38 /*******************************核心算法*********************************************/ 39 40 for(i=0; tempchar<=c; i++,tempchar++)//从最中间列从上往下控制行 41 { 42 int m = 1; 43 char temp = tempchar; //需要保存tempchar的一个临时变量,保证tempchar在while循环中不被改变 44 tem[i][len] = tempchar; //控制最中间的一列 45 46 47 while('A' != temp) //从行最中间左右控制列 48 { 49 tem[i][len-m]=tem[i][len+m]=--temp; 50 m++; 51 } 52 } 53 54 /*******************************核心算法*********************************************/ 55 56 57 for(i=0; i<len; i++) //打印出金字塔图案 58 { 59 for(j=0; j<len2; j++) 60 { 61 printf("%c",tem[i][j]); 62 } 63 printf("\n"); 64 } 65 }
求float型数的幂
1 /*用循环的方法实现,返回一个float 类型数的某个整数次幂,保留六位小数*/ 2 /* 3 *@author: 成鹏致远 4 *@net: http://infodown.tap.cn 5 */ 6 7 #include <stdio.h> 8 #include <math.h> 9 10 float my_power(float cardinal, int pow); //返回cardinal的pow次幂 11 12 int main() 13 { 14 float cardinal; //底数 15 int pow; //幂 16 17 printf("Please input a float cardinal and a int pow(3.14,-2):"); 18 scanf("%f,%d",&cardinal,&pow); 19 20 printf("%f的%d次幂是:%.6f \n",cardinal,pow,my_power(cardinal,pow)); 21 22 return 0; 23 } 24 25 float my_power(float cardinal, int pow) 26 { 27 float result = 1.0; 28 int abs_pow = abs(pow); 29 30 if(0 != abs_pow) //非0次幂 31 { 32 while(abs_pow--) 33 { 34 result *= pow>0?cardinal:1/cardinal; 35 } 36 } 37 else //0次幂 38 { 39 result =1; 40 } 41 return result; 42 }
输出小于指定数的所有素数
1 /* 2 * 接受一个整数输入,然后显示所有小于或等于该数的素数 3 * 编译时请加 -lm 选项,链接到 math 库 4 * author:成鹏致远 5 * net:infodown.tap.cn 6 */ 7 8 #include <stdio.h> 9 #include <stdbool.h> 10 #include <math.h> 11 12 bool IsPrime(int a);//判断是否为素数 13 void PoutPrime(int a);//输出所有小于或等于该数的素数 14 15 int main() 16 { 17 int nem; 18 19 printf("Please input a number:"); 20 scanf("%d",&nem); 21 22 PoutPrime(nem); 23 24 return 0; 25 } 26 27 bool IsPrime(int a)//判断是否为素数 28 { 29 int i; 30 int j = sqrt(a); 31 32 for(i=2; i<=j; i++) 33 { 34 if(0 == a % i) 35 { 36 return false; 37 } 38 } 39 return true; 40 } 41 42 void PoutPrime(int a)//输出所有小于或等于该数的素数 43 { 44 printf("小于或等于%d 的所有素数列表:\t",a); 45 while(a) 46 { 47 if(IsPrime(a)) 48 { 49 printf("%d\t",a); 50 } 51 a--; 52 } 53 printf("\n"); 54 }
辗转相除法求最大公约数(铺砖)
1 /* 2 * 返回两个整数的最大公约数,用辗转相除法求最大公约数 3 * 辗转相除法:铺地砖 4 * author:成鹏致远 5 * net:infodown.tap.cn 6 */ 7 8 #include <stdio.h> 9 10 int Divisor(int a, int b) //最大公约数 11 { 12 int temp; 13 14 if(a < b) 15 { 16 a = a ^ b; 17 b = a ^ b; 18 a = a ^ b; 19 } 20 while(0 != b) 21 { 22 temp = a % b; 23 a = b; 24 b = temp; 25 } 26 return a; //最大公约数 27 //最大公倍数为两数的乘积除以最大公约数 28 } 29 30 int main() 31 { 32 int a,b; 33 34 printf("Please input two numbers:"); 35 scanf("%d%d",&a,&b); 36 37 printf("%d 和%d 的最大公约数是%d \n",a,b,Divisor(a,b)); 38 }
递归实现汉诺塔(递归思想)
1 /* 2 * 递归实现汉诺塔 3 * @author:成鹏致远 4 * @net:infodown.tap.cn 5 */ 6 7 #include <stdio.h> 8 9 void move(char a, char b)//实现汉诺塔的移动 10 { 11 printf("%c—>%c \n",a,b); 12 } 13 14 15 /* 16 * 功 能: 递归实现汉诺塔 17 * n : 盘子个数 18 * a,b,c: 三个盘座 19 */ 20 void han_tower(int n, char a, char b, char c) 21 { 22 if(1==n) 23 { 24 move(a,c); 25 } 26 else 27 { 28 //将前n-1个盘子从a借助c移动到b 29 han_tower(n-1,a,c,b); 30 //将a上的第n个盘子移动到c 31 move(a,c); 32 //将剩下的n-1个盘子从b借助a移动到c 33 han_tower(n-1,b,a,c); 34 } 35 } 36 37 int main() 38 { 39 int num; 40 41 printf("Pls input the number of diskes:"); 42 scanf("%d",&num); 43 printf("the step to moving %d diskes: \n",num); 44 han_tower(num,'A','B','C'); 45 46 return 0; 47 }
乒乓球比赛对手配对(匹配)
1 /* 2 题目:两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定 3 比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出 4 三队赛手的名单。 5 */ 6 7 /* 8 * @author: 成鹏致远 9 * @net: http://infodown.tap.cn 10 */ 11 12 #include <stdio.h> 13 14 int main(void) 15 { 16 char i,j,k; 17 for(i='x';i<='z';i++)//a对手 18 { 19 for(j='x';j<='z';j++)//b对手 20 { 21 if(i!=j)//a,b同对 22 { 23 for(k='x';k<='z';k++)//c对手 24 { 25 if(i!=k&&j!=k)//a,b,c同对 26 { 27 if(i!='x' && k!='x' && k!='z')//a不和x比,c不和x,z比 28 printf("order is a--%c\tb--%c\tc--%c \n",i,j,k); 29 } 30 } 31 } 32 } 33 } 34 35 return 0; 36 }
函数区间求最大值(方法)
1 /* 2 编程:设x取值为区间[1,20]的整数,求函数f(x)=x-sin(x)- cos(x)的最大值 3 要求使用自定义函数实现f(x)功能 4 */ 5 6 /* 7 * @author: 成鹏致远 8 * @net: http://infodown.tap.cn 9 */ 10 11 #include "stdio.h" 12 #include "math.h" 13 double f() 14 { 15 int i; 16 double max=0,x; 17 for(i=1;i<=20;i++) 18 { 19 x=i-sin(i)-cos(i); 20 if(x-max>1e-6) 21 max=x; 22 } 23 return max; 24 25 } 26 main() 27 { 28 printf("%lf",f()); 29 getchar(); 30 }
分解质因数
1 /* 2 题目:将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。 3 程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成: 4 (1)如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印出即可。 5 (2)如果n<>k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你n, 6 重复执行第一步。 7 (3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步。 8 */ 9 10 #include <stdio.h> 11 #include <math.h> 12 13 main() 14 { 15 int n,i; 16 printf("please input a number:\n"); 17 scanf("%d",&n); 18 printf("%d=",n); 19 for(i=2;i<=sqrt(n);i++) 20 { 21 while(n!=i) 22 { 23 if(n%i==0) 24 { 25 printf("%d*",i); 26 n=n/i; 27 } 28 else 29 break; 30 } 31 } 32 printf("%d \n",n); 33 }
古代买鸡问题
1 /* 2 编程解决如下问题:鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一。 3 百钱买百鸡,问鸡翁,鸡母,鸡雏各几何? 4 5 解决方案:数学问题,先用数学方法解决 6 1、设鸡翁、鸡母、鸡雏分别a、b、c只 7 2、5a+3b+c/3=100 8 3、a+b+c=100 9 4、解得:b=(100-7*a)/4; 10 c=(300+3*a)/4; 11 12 */ 13 14 /* 15 * @author: 成鹏致远 16 * @net: http://infodown.tap.cn 17 */ 18 19 #include<stdio.h> 20 21 void main() 22 { 23 int a,b,c; 24 for(a=0;a<20;a++) 25 { 26 b=(100-7*a)/4; 27 c=(300+3*a)/4; 28 if(a+b+c==100&&a>=0&&b>=0&&c>=0) 29 { 30 printf("%d,%d,%d\n",a,b,c); 31 } 32 } 33 }
字符串交叉连接
1 //输入两个字符串,要求将这两个字符串交叉连接。如串1为"ABCD",串2为"123456",则合并后的串为"A1B2C3D456"。 2 3 /* 4 * @author: 成鹏致远 5 * @net: http://infodown.tap.cn 6 */ 7 8 #include<stdio.h> 9 #include<stdlib.h> 10 void main() 11 { 12 char a[20],s[20],*p1,*p2; 13 gets(a); 14 gets(s); 15 p1=a; 16 p2=s; 17 while(1) 18 { 19 if(*p1!='\0') 20 { 21 printf("%c",*p1);p1++; 22 } 23 if(*p2!='\0') 24 { 25 printf("%c",*p2); 26 p2++; 27 } 28 if(*p1=='\0' && *p2=='\0') 29 exit(0); 30 } 31 }
完数
1 /* 2 题目:一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3.编程 3 找出1000以内的所有完数。 4 */ 5 6 /* 7 * @author: 成鹏致远 8 * @net: http://infodown.tap.cn 9 */ 10 11 #include <stdio.h> 12 13 int main(void) 14 { 15 static int k[10]; 16 int i,j,n,s; 17 for(j=2;j<1000;j++) 18 { 19 n=-1; 20 s=j; 21 for(i=1;i<=j/2;i++) 22 { 23 if((j%i)==0) //因子 24 { 25 n++; 26 s=s-i; //减到0则是完数 27 k[n]=i; 28 } 29 } 30 if(s==0) 31 { 32 printf("%d 是一个完数 \n%d=",j,j); 33 for(i=0;i<n;i++) 34 printf("%d+",k[i]); 35 printf("%d \n",k[n]); 36 } 37 } 38 39 return 0; 40 }
容器分水移动(算法)
1 /* 2 编程解决如下数学问题:有12升水,怎样利用一个8升 3 和一个5升的容器将水分为两个6升?要求以如下格式 4 打印出分水步骤。 5 a12 b8 c5 6 12 0 0 7 * * * ( “*”表示当前状态下每个容器的盛水量) 8 ...... 9 6 6 0 10 */ 11 12 /* 13 * @author: 成鹏致远 14 * @net: http://infodown.tap.cn 15 */ 16 17 #include <stdio.h> 18 19 20 void move(int *ai,int *aj,int aiContainer,int ajContainer) //将油从一个容器导倒入另外一个容器 21 { //移动容器目前盛水量,接收容器目前盛水量,移动容器容量,接收容器容量 22 23 if(aiContainer>ajContainer) //移动容器容量>接收容器容量 24 { 25 if(*ai+*aj>ajContainer) //将油倒入接收容器中,移动容器有剩余 26 { 27 *ai=*ai-(ajContainer-*aj); 28 *aj=*aj+ajContainer-*aj; 29 } 30 else //将油倒入接收容器中,移动容器无剩余 31 { 32 *aj=*ai+*aj; 33 *ai=*ai-*ai; 34 } 35 } 36 else //移动容器容量<接收容器容量,则全部倒入接收容器中 37 { 38 *aj=*ai+*aj; 39 *ai=0; 40 } 41 } 42 43 int main(void) 44 { 45 int a[3]={12,0,0},i,m=0; 46 int container[3]={12,8,5}; 47 printf("%-8s%-8s%-8s\n","a12","b8","c5"); 48 printf("%-8d%-8d%-8d\n",a[0],a[1],a[2]); 49 while(a[0]!=6) 50 { 51 for(i=0;i<3;i++)//循环三次,分别从a->b,b->c,c->a 52 { 53 move(&a[i],&a[(i+1)%3],container[i],container[(i+1)%3]); 54 m++; 55 printf("%-8d%-8d%-8d\n",a[0],a[1],a[2]); 56 if(a[0]==6 && a[1]==6) 57 { 58 printf("The total number is %d to reach success!",m); 59 getchar(); 60 return 0; 61 } 62 } 63 move(&a[1],&a[2],container[1],container[2]);//b->c 64 printf("%-8d%-8d%-8d\n",a[0],a[1],a[2]); 65 m++; 66 if(a[0]==6 && a[1]==6) 67 { 68 printf("The total number is %d to reach success!",m); 69 break; 70 } 71 } 72 getchar(); 73 return 0; 74 }
猴子吃桃问题(逆向思维)
1 /* 2 猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个 3 第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下 4 的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。 5 1.程序分析:采取逆向思维的方法,从后往前推断。 6 */ 7 8 /* 9 * @author: 成鹏致远 10 * @net: http://infodown.tap.cn 11 */ 12 13 #include <stdio.h> 14 15 int main(void) 16 { 17 int day,x1,x2; 18 day=9; 19 x2=1; 20 while(day>0) 21 { 22 x1=(x2+1)*2; 23 x2=x1; 24 day--; 25 } 26 printf("the total is %d \n",x1); 27 28 return 0; 29 }
统计字符数字等
1 /* 2 题目:输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数 3 */ 4 5 /* 6 * @author: 成鹏致远 7 * @net: http://infodown.tap.cn 8 */ 9 10 #include <stdio.h> 11 12 int main(void) 13 { 14 char c; 15 int letters=0,space=0,digit=0,others=0; 16 printf("please input some characters: \n"); 17 while((c=getchar())!='\n') 18 { 19 if(c>='a'&&c<='z'||c>='A'&&c<='Z') 20 letters++; 21 else if(c==' ') 22 space++; 23 else if(c>='0'&&c<='9') 24 digit++; 25 else 26 others++; 27 } 28 printf("all in all:char=%d space=%d digit=%d others=%d \n",letters,space,digit,others); 29 30 return 0; 31 }
贪心算法用例(够纠结的)
1 /* 2 编程解决如下问题。 3 请在整数n=742683613984中删除8个数字,使得余下的数字按原次序组成的新数最小。要求如下: 4 (1)整数n和删除数字的个数“8”在源程序中完成赋值,程序直接输出运行结果; 5 (2)程序结果输出先后被删除的数字(之间以逗号分隔)和删除后所得的最小数。 6 (提示:整数n可以以字符数组的方式定义、赋值和处理) 7 8 编写思路: 9 在前9位数字中寻找最小数字a1,记下该最小数字的位置b1,a1前面所有数字是该删除的, 10 个数m=b1-1,然后从a1后面开始继续操作,变为删除8-m个数字,从a1后8-m+1个数字中找最小值a2, 11 记下b2,删除a1与a2之间的数字,个数b2-b1-1。m=m+b2-b1-1.如此下去直至m=8,停止操作, 12 输出a1a2……及最后一个a和之后的数字。 13 14 程序一是正确的,程序二是错误的 15 一和二的差别主要是在删除字符序列的顺序上 16 */ 17 18 /* 19 * @author: 成鹏致远 20 * @net: http://infodown.tap.cn 21 */ 22 23 //程序一:贪心算法 24 25 #include <string.h> 26 #include <stdio.h> 27 28 int main() 29 { 30 int i,m=8,t=0; 31 char p[10]; 32 char s[]="742683613984"; 33 for (i=0;i<12;i++) 34 { 35 while(t&&p[t-1]>s[i]&&m) //用p数组中的每一个元素和当前s[i]比较 36 { 37 t--,m--; //进入循环意味着s[i]比p[--t]小,需要将p[--t]输出,并且m-1 38 printf("%c",p[t]); 39 if(m) //未删除所有符合条件的元素之前,用逗号将各元素分开 40 printf(","); 41 } 42 p[t++]=s[i]; //p数组依次暂存前一位比后一位小的数字 43 } //循环结束后p数组中存储着最小的四位数 44 p[t]=0; //字符数组结束 45 printf("\n"); 46 puts(p); 47 return 0; 48 } 49 50 51 52 /* 53 //程序二:这个是错误的,程序一和程序二的差别在删除字符序列的顺序 54 55 #include <stdio.h> 56 #include <stdlib.h> 57 58 void main() 59 { 60 char *s="742683613984"; 61 printf("%s\n",s); 62 //去掉8个相当于取4个 63 int a,b,c,d;//下标 64 int aa,bb,cc,dd;//某位数字 65 int ka,kb,kc,kd;//最小值对应的下标 66 int min=10000;//当取4个时,设定初始最小值为5位数 67 int num;//组和的值 68 for(a=0;a<=8;a++) 69 { 70 for(b=1;b<=9;b++) 71 { 72 for(c=2;c<=10;c++) 73 { 74 for(d=3;d<=11;d++) 75 { 76 if((a<b) && (b<c) && (c<d) )//保证不重复和先后顺序 77 { 78 aa=s[a]-'0';bb=s[b]-'0';cc=s[c]-'0';dd=s[d]-'0';//字符型转换为整数 79 num=aa*1000+bb*100+cc*10+dd;//求组和数 80 if (num<min)//选择最小值以及下标 81 { 82 min=num; 83 ka=a;kb=b;kc=c;kd=d;//最小值对应的下标 84 } 85 } 86 } 87 } 88 } 89 } 90 91 for(int i=0;i<=11;i++)//输出去掉的数 92 { 93 if(i!=ka && i!=kb && i!=kc && i!=kd) 94 printf("%c\t",s[i]); 95 } 96 printf("\n%d\n",min);//输出最小值 97 system("pause"); 98 } 99 100 101 */ 102