• 算法竞赛入门经典_3.1_数组_逆序输出_开灯问题


    又是新的一天,继续更新.

    今天进入了新的章节,数组和字符串

    1.逆序输出问题:

    先来看代码吧

    #include <stdio.h>
    //逆序输出 2017-8-16
    #define maxn 105
    int a[maxn];
    int main(int argc, char* argv[])
    {
        //int a[maxn];
        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
    ", a[0]);//输出的行首和行尾一般均无空格,所以用两条语句实现输出
        return 0;
    }

    注意:数组一般会声明得稍大一些

    这是一个逆序输出问题,但需要注意的是在定义数组的时候,要在main函数之外定义,如果遇到maxn很大,如1000000,则程序将无法运行,下面截图为证

    直接结束了,所以我们应该放外面,再看

    放外面就正常运行了,然后看看效果截图吧

    2.开灯问题:

    看代码

    //开灯问题 2017-8-16
    
    #include <stdio.h>
    #include <string.h>
    #define maxn 1010
    int a[maxn];
    int main(int argc, char* argv[])
    {
        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("
    ");
        return 0;
    }

      这里有很多新的知识点了,首先是string.h中的memcpy(b,a,sizeof(int)*k)是将a数组复制给b,大小为k,

    如果想全部复制,可以使用memcpy(b,a,sizeof(a)),还有一个函数,也就是本程序出现的memset(a, 0, sizeof(a));

    是将数组a中的数据置为0.

      值得注意的是,我们定义了first变量,这个变量是干什么的呢?很显然它是一个标志是否是第一个数据的变量,

    因为在输出的时候,第一个数前面是不需要空格的.

    看运行结果

    3.蛇形填数:

    这个问题博主还没解决,不知道为什么和书上代码一样,运行却有问题

    搞笑了,博主刚好想贴代码的时候检查了下代码,发现是第22while循环条件搞错了,应该是向上移动x-1 >= 0(我之前写成了<,这告诉大家,写代码如果遇到了一些很奇怪的运行结果,试着检查自己的代码,特别是循环条件)

    //蛇形填数问题 2017-8-16
    #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));
        x = 0;
        y = n - 1;
        a[x][y] = 1;
        tot = 1;
        //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("%3d", a[x][y]);
            printf("
    ");
        }
        return 0;
    }

    分析:从1开始填写,设置笔的起始坐标为(x,y),也就是(0,n-1)了,x代表行,y代表列,所以笔的移动轨迹是下,下,下,左,左,左,上,上,上,右,右,下,下,左,上

    在这里我们只需要判断两个条件

    • 一个是是否超出边界,在下移动的轨迹中,也就是x+1<n
    • 另一个是是否填了以前填过得格子,所以是a[x+1][y] == 0的条件,简写为!a[x+1][y]

    有了这一思路,就好解了看运行结果吧

    在这一练习中,我们可以学到的:

    1)可以利用c语言简洁的语法,但前提是保持代码的可读性

    2)在很多情况下,最好是在一件事之前检查是不是可以做,而不是在做完之后再后悔,因为"悔棋"往往是比较麻烦的.

    发现做算法,其中还是可以学到很多,而且很有趣

    生活中也是,我们在做某件事的时候,要考虑是不是应该做,因为后悔药是很难买的,就好比博主熬夜写博客,

    现在还是可以接受的,如果天天如此身体也是会吃不消的,好了今天到这里了,各位同行们也早点休息,注意身体.

    晚安世界!

  • 相关阅读:
    基于vue的购物车清单
    圣杯布局和双飞翼布局
    正则限制input负数输入
    vue.js devtools图标不亮
    将二维数组转换成一维数组(基于reduce)
    基于PROMISE解决回调地狱问题
    封装AJAX库(参考JQ)
    for in和for of的区别
    抢购倒计时的实现
    git clone --depth=1 后获取其他分支
  • 原文地址:https://www.cnblogs.com/ncgds/p/7376790.html
Copyright © 2020-2023  润新知