zoukankan      html  css  js  c++  java
  • C语言复习笔记-17种小算法-解决实际问题

    C语言复习笔记-17种小算法-解决实际问题

    判断日期为一年中的第几天(考虑闰年)

     View Code

    /*
    * 计算该日在本年中是第几天,注意闰年问题
    * 以3月5日为例,应该先把前两个月的加起来,然后再加上5天即本年的第几天
    * 特殊情况,闰年且输入月份大于3时需考虑多加一天
    */

    /*
    *@author: 成鹏致远
    *@net: http://infodown.tap.cn
    */

    #include <stdio.h>
    #include <stdbool.h>

    struct year_mon_day
    {
    int year;
    int mon;
    int day;
    };

    int main()
    {
    int i;
    int sum;//总天数
    bool flag = false;//闰年标志
    struct year_mon_day ymd;

    printf("Pls input year,mon day:");
    scanf("%d%d%d",&ymd.year,&ymd.mon,&ymd.day);

    switch(ymd.mon)
    {
    case 1:
    sum = 0;
    break;
    case 2:
    sum = 31;
    break;
    case 3:
    sum = 59;
    break;
    case 4:
    sum = 90;
    break;
    case 5:
    sum = 120;
    break;
    case 6:
    sum = 151;
    break;
    case 7:
    sum = 181;
    break;
    case 8:
    sum = 212;
    break;
    case 9:
    sum = 243;
    break;
    case 10:
    sum = 173;
    break;
    case 11:
    sum = 304;
    break;
    case 12:
    sum = 334;
    break;
    default:
    printf("data error ");
    return 1;
    }
    sum += ymd.day;

    if(ymd.year/100 || (ymd.year%4 && ymd.year%100 != 0))
    {
    flag = true;
    }

    if(1==flag && ymd.mon>2)
    {
    sum++;
    }

    printf("%d年%d月%d日 是%d年的第%d天 ",ymd.year,ymd.mon,ymd.day,ymd.year,sum);

    return 0;
    }

    十进制转十六进制

     View Code

    /*函数实现输入一个十进制数,输出对应的十六进制数*/
    /*
    *@author: 成鹏致远
    *@net: http://infodown.tap.cn
    */

    #include <stdio.h>
    #include <stdbool.h>
    #define LIM 32

    int main(void)
    {
    int decimal;
    bool negative = false;
    printf("pls input the integer to convert: ");

    if(!scanf("%d", &decimal))
    {
    printf("we need an integer, Bye-bye! ");
    return -1;
    }
    if(decimal < 0)
    {
    negative = true;
    decimal *= -1;
    }

    int i, num[LIM];
    for(i=0; i<LIM && decimal!=0; i++)
    {
    num[i] = decimal%16;
    decimal /= 16;
    }

    int j;
    if(negative)
    printf("answer: -0x");
    else
    printf("answer: 0x");

    for(j=i; j>0; j--){
    switch(num[j-1]){
    case 10:
    printf("a");
    break;
    case 11:
    printf("b");
    break;
    case 12:
    printf("c");
    break;
    case 13:
    printf("d");
    break;
    case 14:
    printf("e");
    break;
    case 15:
    printf("f");
    break;
    default:
    printf("%d", num[j-1]);
    break;
    } //switch
    } //for
    printf(" ");

    return 0;
    }

    打印指定的字母金字塔(技巧)

     View Code

    /*
    * 产生一个字母金字塔图案
    * author:成鹏致远
    * net:infodown.tap.cn
    */

    #include <stdio.h>

    void PintLetterPic(char); //打印出金字搭字母图案

    int main()
    {
    char letter;

    printf("Please input a capital letter:");
    scanf("%c",&letter);

    PintLetterPic(letter);

    return 0;
    }

    void PintLetterPic(char c) //打印出金字搭字母图案
    {
    int len = c - 'A'+1; //注意这里需要+1!!!
    int len2 = 2*len;
    char tem[100][200];
    int i,j;
    char tempchar = 'A';

    for(i=0; i<100; i++) //初始化二维数组
    {
    for(j=0; j<200; j++)
    {
    tem[i][j] = ' ';
    }
    }
    /*******************************核心算法*********************************************/

    for(i=0; tempchar<=c; i++,tempchar++)//从最中间列从上往下控制行
    {
    int m = 1;
    char temp = tempchar; //需要保存tempchar的一个临时变量,保证tempchar在while循环中不被改变
    tem[i][len] = tempchar; //控制最中间的一列


    while('A' != temp) //从行最中间左右控制列
    {
    tem[i][len-m]=tem[i][len+m]=--temp;
    m++;
    }
    }

    /*******************************核心算法*********************************************/


    for(i=0; i<len; i++) //打印出金字塔图案
    {
    for(j=0; j<len2; j++)
    {
    printf("%c",tem[i][j]);
    }
    printf(" ");
    }
    }

    求float型数的幂

     View Code

    /*用循环的方法实现,返回一个float 类型数的某个整数次幂,保留六位小数*/
    /*
    *@author: 成鹏致远
    *@net: http://infodown.tap.cn
    */

    #include <stdio.h>
    #include <math.h>

    float my_power(float cardinal, int pow); //返回cardinal的pow次幂

    int main()
    {
    float cardinal; //底数
    int pow; //幂

    printf("Please input a float cardinal and a int pow(3.14,-2):");
    scanf("%f,%d",&cardinal,&pow);

    printf("%f的%d次幂是:%.6f ",cardinal,pow,my_power(cardinal,pow));

    return 0;
    }

    float my_power(float cardinal, int pow)
    {
    float result = 1.0;
    int abs_pow = abs(pow);

    if(0 != abs_pow) //非0次幂
    {
    while(abs_pow--)
    {
    result *= pow>0?cardinal:1/cardinal;
    }
    }
    else //0次幂
    {
    result =1;
    }
    return result;
    }

    输出小于指定数的所有素数

     View Code

    /*
    * 接受一个整数输入,然后显示所有小于或等于该数的素数
    * 编译时请加 -lm 选项,链接到 math 库
    * author:成鹏致远
    * net:infodown.tap.cn
    */

    #include <stdio.h>
    #include <stdbool.h>
    #include <math.h>

    bool IsPrime(int a);//判断是否为素数
    void PoutPrime(int a);//输出所有小于或等于该数的素数

    int main()
    {
    int nem;

    printf("Please input a number:");
    scanf("%d",&nem);

    PoutPrime(nem);

    return 0;
    }

    bool IsPrime(int a)//判断是否为素数
    {
    int i;
    int j = sqrt(a);

    for(i=2; i<=j; i++)
    {
    if(0 == a % i)
    {
    return false;
    }
    }
    return true;
    }

    void PoutPrime(int a)//输出所有小于或等于该数的素数
    {
    printf("小于或等于%d 的所有素数列表: ",a);
    while(a)
    {
    if(IsPrime(a))
    {
    printf("%d ",a);
    }
    a--;
    }
    printf(" ");
    }

    辗转相除法求最大公约数(铺砖)

     View Code

    /*
    * 返回两个整数的最大公约数,用辗转相除法求最大公约数
    * 辗转相除法:铺地砖
    * author:成鹏致远
    * net:infodown.tap.cn
    */

    #include <stdio.h>

    int Divisor(int a, int b) //最大公约数
    {
    int temp;

    if(a < b)
    {
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    }
    while(0 != b)
    {
    temp = a % b;
    a = b;
    b = temp;
    }
    return a; //最大公约数
    //最大公倍数为两数的乘积除以最大公约数
    }

    int main()
    {
    int a,b;

    printf("Please input two numbers:");
    scanf("%d%d",&a,&b);

    printf("%d 和%d 的最大公约数是%d ",a,b,Divisor(a,b));
    }

    递归实现汉诺塔(递归思想)

     View Code

    /*
    * 递归实现汉诺塔
    * @author:成鹏致远
    * @net:infodown.tap.cn
    */

    #include <stdio.h>

    void move(char a, char b)//实现汉诺塔的移动
    {
    printf("%c—>%c ",a,b);
    }


    /*
    * 功 能: 递归实现汉诺塔
    * n : 盘子个数
    * a,b,c: 三个盘座
    */
    void han_tower(int n, char a, char b, char c)
    {
    if(1==n)
    {
    move(a,c);
    }
    else
    {
    //将前n-1个盘子从a借助c移动到b
    han_tower(n-1,a,c,b);
    //将a上的第n个盘子移动到c
    move(a,c);
    //将剩下的n-1个盘子从b借助a移动到c
    han_tower(n-1,b,a,c);
    }
    }

    int main()
    {
    int num;

    printf("Pls input the number of diskes:");
    scanf("%d",&num);
    printf("the step to moving %d diskes: ",num);
    han_tower(num,'A','B','C');

    return 0;
    }

    乒乓球比赛对手配对(匹配)

     View Code

    /*
    题目:两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定
        比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出
        三队赛手的名单。
    */

    /*
    * @author: 成鹏致远
    * @net: http://infodown.tap.cn
    */

    #include <stdio.h>

    int main(void)
    {
    char i,j,k;
    for(i='x';i<='z';i++)//a对手
    {
    for(j='x';j<='z';j++)//b对手
    {
    if(i!=j)//a,b同对
    {
    for(k='x';k<='z';k++)//c对手
    {
    if(i!=k&&j!=k)//a,b,c同对
    {
    if(i!='x' && k!='x' && k!='z')//a不和x比,c不和x,z比
    printf("order is a--%c b--%c c--%c ",i,j,k);
    }
    }
    }
    }
    }

    return 0;
    }

    函数区间求最大值(方法)

     View Code

    /*
    编程:设x取值为区间[1,20]的整数,求函数f(x)=x-sin(x)- cos(x)的最大值
    要求使用自定义函数实现f(x)功能
    */

    /*
    * @author: 成鹏致远
    * @net: http://infodown.tap.cn
    */

    #include "stdio.h"
    #include "math.h"
    double f()
    {
    int i;
    double max=0,x;
    for(i=1;i<=20;i++)
    {
    x=i-sin(i)-cos(i);
    if(x-max>1e-6)
    max=x;
    }
    return max;

    }
    main()
    {
    printf("%lf",f());
    getchar();
    }

    分解质因数

     View Code

    /*
    题目:将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。
    程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成:
    (1)如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印出即可。
    (2)如果n<>k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你n,
      重复执行第一步。
    (3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步。
    */

    #include <stdio.h>
    #include <math.h>

    main()
    {
    int n,i;
    printf("please input a number: ");
    scanf("%d",&n);
    printf("%d=",n);
    for(i=2;i<=sqrt(n);i++)
    {
    while(n!=i)
    {
    if(n%i==0)
    {
    printf("%d*",i);
    n=n/i;
    }
    else
    break;
    }
    }
    printf("%d ",n);
    }

    古代买鸡问题

     View Code

    /*
    编程解决如下问题:鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一。
    百钱买百鸡,问鸡翁,鸡母,鸡雏各几何?

    解决方案:数学问题,先用数学方法解决
    1、设鸡翁、鸡母、鸡雏分别a、b、c只
    2、5a+3b+c/3=100
    3、a+b+c=100
    4、解得:b=(100-7*a)/4;
    c=(300+3*a)/4;

    */

    /*
    * @author: 成鹏致远
    * @net: http://infodown.tap.cn
    */

    #include<stdio.h>

    void main()
    {
    int a,b,c;
    for(a=0;a<20;a++)
    {
    b=(100-7*a)/4;
    c=(300+3*a)/4;
    if(a+b+c==100&&a>=0&&b>=0&&c>=0)
    {
    printf("%d,%d,%d ",a,b,c);
    }
    }
    }

    字符串交叉连接

     View Code

    //输入两个字符串,要求将这两个字符串交叉连接。如串1为"ABCD",串2为"123456",则合并后的串为"A1B2C3D456"。

    /*
    * @author: 成鹏致远
    * @net: http://infodown.tap.cn
    */

    #include<stdio.h>
    #include<stdlib.h>   
    void main()
    {
    char a[20],s[20],*p1,*p2;
    gets(a);
    gets(s);
    p1=a;
    p2=s;
    while(1)
    {
    if(*p1!='')
    {
    printf("%c",*p1);p1++;
    }
    if(*p2!='')
    {
    printf("%c",*p2);
    p2++;
    }
    if(*p1=='' && *p2=='')
    exit(0);
    }
    }

    完数

     View Code

    /*
    题目:一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3.编程
        找出1000以内的所有完数。
    */

    /*
    * @author: 成鹏致远
    * @net: http://infodown.tap.cn
    */

    #include <stdio.h>

    int main(void)
    {
    static int k[10];
    int i,j,n,s;
    for(j=2;j<1000;j++)
    {
    n=-1;
    s=j;
    for(i=1;i<=j/2;i++)
    {
    if((j%i)==0) //因子
    {
    n++;
    s=s-i; //减到0则是完数
    k[n]=i;
    }
    }
    if(s==0)
    {
    printf("%d 是一个完数 %d=",j,j);
    for(i=0;i<n;i++)
    printf("%d+",k[i]);
    printf("%d ",k[n]);
    }
    }

    return 0;
    }

    容器分水移动(算法)

     View Code

    /*
    编程解决如下数学问题:有12升水,怎样利用一个8升
    和一个5升的容器将水分为两个6升?要求以如下格式
    打印出分水步骤。
    a12 b8 c5
    12 0 0
    * * * ( “*”表示当前状态下每个容器的盛水量)
    ......
    6 6 0
    */

    /*
    * @author: 成鹏致远
    * @net: http://infodown.tap.cn
    */

    #include <stdio.h>


    void move(int *ai,int *aj,int aiContainer,int ajContainer) //将油从一个容器导倒入另外一个容器
    { //移动容器目前盛水量,接收容器目前盛水量,移动容器容量,接收容器容量

    if(aiContainer>ajContainer) //移动容器容量>接收容器容量
    {
    if(*ai+*aj>ajContainer) //将油倒入接收容器中,移动容器有剩余
    {
    *ai=*ai-(ajContainer-*aj);
    *aj=*aj+ajContainer-*aj;
    }
    else //将油倒入接收容器中,移动容器无剩余
    {
    *aj=*ai+*aj;
    *ai=*ai-*ai;
    }
    }
    else //移动容器容量<接收容器容量,则全部倒入接收容器中
    {
    *aj=*ai+*aj;
    *ai=0;
    }
    }

    int main(void)
    {
    int a[3]={12,0,0},i,m=0;
    int container[3]={12,8,5};
    printf("%-8s%-8s%-8s ","a12","b8","c5");
    printf("%-8d%-8d%-8d ",a[0],a[1],a[2]);
    while(a[0]!=6)
    {
    for(i=0;i<3;i++)//循环三次,分别从a->b,b->c,c->a
    {
    move(&a[i],&a[(i+1)%3],container[i],container[(i+1)%3]);
    m++;
    printf("%-8d%-8d%-8d ",a[0],a[1],a[2]);
    if(a[0]==6 && a[1]==6)
    {
    printf("The total number is %d to reach success!",m);
    getchar();
    return 0;
    }
    }
    move(&a[1],&a[2],container[1],container[2]);//b->c
    printf("%-8d%-8d%-8d ",a[0],a[1],a[2]);
    m++;
    if(a[0]==6 && a[1]==6)
    {
    printf("The total number is %d to reach success!",m);
    break;
    }
    }
    getchar();
    return 0;
    }

    猴子吃桃问题(逆向思维)

     View Code

    /*
    猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个
        第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下
        的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。
    1.程序分析:采取逆向思维的方法,从后往前推断。
    */

    /*
    * @author: 成鹏致远
    * @net: http://infodown.tap.cn
    */

    #include <stdio.h>

    int main(void)
    {
    int day,x1,x2;
    day=9;
    x2=1;
    while(day>0)
    {
    x1=(x2+1)*2;
    x2=x1;
    day--;
    }
    printf("the total is %d ",x1);

    return 0;
    }

    统计字符数字等

     View Code

    /*
    题目:输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数
    */

    /*
    * @author: 成鹏致远
    * @net: http://infodown.tap.cn
    */

    #include <stdio.h>

    int main(void)
    {
    char c;
    int letters=0,space=0,digit=0,others=0;
    printf("please input some characters: ");
    while((c=getchar())!=' ')
    {
    if(c>='a'&&c<='z'||c>='A'&&c<='Z')
    letters++;
    else if(c==' ')
    space++;
    else if(c>='0'&&c<='9')
    digit++;
    else
    others++;
    }
    printf("all in all:char=%d space=%d digit=%d others=%d ",letters,space,digit,others);

    return 0;
    }

    贪心算法用例(够纠结的)

     View Code

    /*
    编程解决如下问题。
      请在整数n=742683613984中删除8个数字,使得余下的数字按原次序组成的新数最小。要求如下:
      (1)整数n和删除数字的个数“8”在源程序中完成赋值,程序直接输出运行结果;
      (2)程序结果输出先后被删除的数字(之间以逗号分隔)和删除后所得的最小数。
      (提示:整数n可以以字符数组的方式定义、赋值和处理)

    编写思路:
    在前9位数字中寻找最小数字a1,记下该最小数字的位置b1,a1前面所有数字是该删除的,
    个数m=b1-1,然后从a1后面开始继续操作,变为删除8-m个数字,从a1后8-m+1个数字中找最小值a2,
    记下b2,删除a1与a2之间的数字,个数b2-b1-1。m=m+b2-b1-1.如此下去直至m=8,停止操作,
    输出a1a2……及最后一个a和之后的数字。

    程序一是正确的,程序二是错误的
    一和二的差别主要是在删除字符序列的顺序上
    */

    /*
    * @author: 成鹏致远
    * @net: http://infodown.tap.cn
    */

    //程序一:贪心算法

    #include <string.h>
    #include <stdio.h>

    int main()
    {
    int i,m=8,t=0;
    char p[10];
    char s[]="742683613984";
    for (i=0;i<12;i++)
    {
    while(t&&p[t-1]>s[i]&&m) //用p数组中的每一个元素和当前s[i]比较
    {
    t--,m--; //进入循环意味着s[i]比p[--t]小,需要将p[--t]输出,并且m-1
    printf("%c",p[t]);
    if(m) //未删除所有符合条件的元素之前,用逗号将各元素分开
    printf(",");
    }
    p[t++]=s[i]; //p数组依次暂存前一位比后一位小的数字
    } //循环结束后p数组中存储着最小的四位数
    p[t]=0; //字符数组结束
    printf(" ");
    puts(p);
    return 0;
    }



    /*
    //程序二:这个是错误的,程序一和程序二的差别在删除字符序列的顺序

    #include <stdio.h>
    #include <stdlib.h>

    void main()
    {
    char *s="742683613984";
    printf("%s ",s);
    //去掉8个相当于取4个
    int a,b,c,d;//下标
    int aa,bb,cc,dd;//某位数字
    int ka,kb,kc,kd;//最小值对应的下标
    int min=10000;//当取4个时,设定初始最小值为5位数
    int num;//组和的值
    for(a=0;a<=8;a++)
    {
    for(b=1;b<=9;b++)
    {
    for(c=2;c<=10;c++)
    {
    for(d=3;d<=11;d++)
    {
    if((a<b) && (b<c) && (c<d) )//保证不重复和先后顺序
    {
    aa=s[a]-'0';bb=s[b]-'0';cc=s[c]-'0';dd=s[d]-'0';//字符型转换为整数
    num=aa*1000+bb*100+cc*10+dd;//求组和数
    if (num<min)//选择最小值以及下标
    {
    min=num;
    ka=a;kb=b;kc=c;kd=d;//最小值对应的下标
    }
    }
    }
    }
    }
    }

    for(int i=0;i<=11;i++)//输出去掉的数
    {
    if(i!=ka && i!=kb && i!=kc && i!=kd)
    printf("%c ",s[i]);
    }
    printf(" %d ",min);//输出最小值
    system("pause");
    }


    */

    本文出自“成鹏致远” 博客,转载请务必保留此出处:lcw.cnblogs.com 「PS:并在评论处留下转载地址,谢谢」
     
    分类: C/C++
  • 相关阅读:
    C
    B
    D
    I
    B
    E
    B
    L
    H
    bzoj3276磁力 两种要求下的最大值:分块or线段树+拓扑
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3205593.html
Copyright © 2011-2022 走看看