算法入门经典第三章(上)

逆序输出

读入一些整数然后逆序输出,将你所输入的每个数字存入到数组a[maxn]中,然后利用for循环逆序输出,输入完了以后别忘了先按回车再按crtl+z,强制输出,要不然会无限输入的2333.这段程序运行是这样的:(给你个例子( ̄▽ ̄)")如果输入12 33 55 89 ,则输出 89 55 33 12.【主要是a[n++]=x这个地方很高效】

#include<stdio.h>
#define maxn 105
int a[maxn];
int main()
{
    int x,n=0;
    while(scanf("%d",&x)==1)
      a[n++]=x;
    for(int i=n-1;i>=1;i--)
        printf("%d ",a[i]);
      printf("%d\n",a[0]);
      return 0;
}

开灯问题

有n个灯,编号为1-n,第1个人把所有灯打开,第2个把2的倍数的灯号打开以此类推。一共k人,最后有哪些灯亮着。

一开始用memset把数组a清零,模拟一开始所有灯都是关了的状态,然后我们发现改变状态灯都是 灯的数量n能被1到k整除的灯,比如题目例子中7 3,第一次改变的是1-7,第二次,2,4,6,第三次3,6;刘汝佳老师用的是a[j]=!a[j]来进行对灯状态的改变,a[j]=!a[j]这个语句就是非零即真,如果a[j]为1那么进行完语句之后就是0,反之为0,最后是1.简言之就是0变成1,1变成0.

拿书上例子7 3来说,①i=1,j=1,j%i==0,a[j]=1(因为memset清零了)j一直到7,都能被整除,代表所有灯都亮。②i=2,j=1不整除不执行语句,所以a[j]还是1,j=2,整除a[j]=0;以此类推,最后a[2],a[4],a[6]=0,其余为1;③i=3情况也是一样的,a[3],a[6]整除,它们再变,a[3]=0,a[6]=1。然后就是控制空格的问题了,a[i]肯定!=0,所以第一次执行这里的时候first=0,此后first一直=0,就是只有第一个输出i,剩下的因为first=0,输出空格+i,最后再来个\n。完美~

#include<stdio.h>
#include<string.h>
#define maxn 1005
int a[maxn];
int main()
{
   int n,k,first=1;
   memset(a,0,sizeof(a));
   scanf("%d%d",&n,&k);
   for(int i=1;i<=k;i++)
    for(int j=1;j<=n;j++)
    if(j%i==0)
    a[j]=!a[j];
   for(int i=1;i<=n;i++)
    if(a[i])
   {
       if(first)
        first=0;
       else
        printf(" ");
       printf("%d",i);
   }
   printf("\n");
   return 0;
}

蛇形填数

二维数组的应用。一开始我们先把n*n的矩阵全部填充0:memset(a,0,sizeof(a)),然后将最右上角的那个0赋值1,tot也赋值成1:tot=a[x=0][y=n-1]=1;tot进行填数,蛇形填数的最后一个数字一定是n*n,所以while(tot<n*n),然后蛇形填数肯定都是先往下走,再往左走,再往上走,再往右走,我们需要一个界限不是吗?要不然它不就会一直往一个地方走而不变方向,而这个界限举例一下while(x+1<n&&!a[x+1][y]),从最右上角开始往下走,x每+1,就走了一步,x+1肯定<n,而!a[x+1][y]和上题一样,一开始我们不是将a[maxn][maxn]清零了吗,就相当于一个界限了,超出n*n的部分都不是0,在n*n里面这个区域里才都是0,满足两个条件才执行语句。然后最右上角a[0][n-1]=1,往下走一个a[1][n-1]就从0变成1,然后进行tot++,赋值a[1][n-1]=2,以此类推。

#include<stdio.h>
#include<string.h>
#define maxn 20
int a[maxn][maxn];
int main()
{
   int n,x,y,tot=0;
   scanf("%d",&n);
   memset(a,0,sizeof(a));
   tot=a[x=0][y=n-1]=1;
   while(tot<n*n)
   {
       while(x+1<n&&!a[x+1][y])
        a[++x][y]=++tot;
       while(y-1>=0&&!a[x][y-1])
        a[x][--y]=++tot;
       while(x-1>=0&&!a[x-1][y])
        a[--x][y]=++tot;
       while(y+1<n&&!a[x][y+1])
        a[x][++y]=++tot;
   }
   for(x=0;x<n;x++)
   {
       for(y=0;y<n;y++)
        printf("%4d",a[x][y]);
        printf("\n");
   }
   return 0;
}

竖式问题

拿书上例子来说输入的2357是一个集合,我们可以把这个集合取名A={2,3,5,7},只要abc,de,x,y,z的元素在这个集合里就算一个合法的竖式。【一开始我没弄明白= =】,比如书上例子abc=775,元素是7,5在集合A中,de=33,元素是3,在集合A中,x=2325,元素是2,3,5在集合A中,y同,z=25575,元素是2,5,7在集合A中。然后abc是个三位数所以从100-999里去找,de是个两位数从10-99里去找。(为什么书上写的是111-999和11到99,这......有问题吧)sprintf(buf,"%d%d%d%d",abc,de,x,y,z)就是将abc,de,x,y,z,变成字符串存入到buf中,比如例子中abc=775,de=33,x=2325,y=2325,z=25575,执行语句之后就是buf[i]={"775332325232525575"},然后strchr(s,buf[i])就是找buf[i]在字符串s中(首次)的位置,如果找不到就返回NULL.

#include<stdio.h>
#include<string.h>
int main()
{
   int count=0;
   char s[20],buf[99];
   scanf("%s",s);
   for(int abc=100;abc<=999;abc++)
    for(int de=10;de<=99;de++)
   {
       int x=abc*(de%10),y=abc*(de/10),z=abc*de;
       sprintf(buf,"%d%d%d%d%d",abc,de,x,y,z);
       int ok=1;
       for(int i=0;i<strlen(buf);i++)
        if(strchr(s,buf[i])==NULL)
        ok=0;
       if(ok)
       {
           printf("<%d>\n",++count);
           printf("%5d\n",abc);
           printf("X%4d\n",de);
           printf("------\n");
           printf("%5d\n",x);
           printf("%4d\n",y);
           printf("------\n");
           printf("%5d\n",z);
           printf("\n");
       }
   }
   printf("The number of solutions = %d\n",count);
   return 0;
}

TeX中的引号

gets竟然被废除了啊w(゚Д゚)w,这么可怜的吗,我还挺常用它来着......

#include<stdio.h>
int main()
{
   int q=1,c;
   while((c=getchar())!=EOF)
   {
       if(c=='"')
       {
           printf("%s",q ? "“" : "''");
           q=!q;
       }
        else
        printf("%c",c);
   }
   return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值