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

Posted easydots的博客园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法竞赛入门经典_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\\n", 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("\\n");
    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("\\n");
    }
    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)在很多情况下,最好是在一件事之前检查是不是可以做,而不是在做完之后再后悔,因为"悔棋"往往是比较麻烦的.

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

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

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

晚安世界!

以上是关于算法竞赛入门经典_3.1_数组_逆序输出_开灯问题的主要内容,如果未能解决你的问题,请参考以下文章

算法竞赛入门经典_4.3_递归

开灯问题(算法竞赛入门经典)

算法竞赛入门经典_1.5_习题练习

算法竞赛入门经典_2_变量及其输入

算法竞赛入门经典_6数据结构基础

算法竞赛入门经典 数组实现树的层序遍历的一个小错误