CCF201604-1 折点计数(100分)序列处理

Posted 海岛Blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF201604-1 折点计数(100分)序列处理相关的知识,希望对你有一定的参考价值。

试题编号: 201604-1
试题名称: 折点计数
时间限制: 1.0s
内存限制: 256.0MB
问题描述:

问题描述
  给定n个整数表示一个商店连续n天的销售量。如果某天之前销售量在增长,而后一天销售量减少,则称这一天为折点,反过来如果之前销售量减少而后一天销售量增长,也称这一天为折点。其他的天都不是折点。如下图中,第3天和第6天是折点。

  给定n个整数a 1, a 2, …, a n表示销售量,请计算出这些天总共有多少个折点。
  为了减少歧义,我们给定的数据保证:在这n天中相邻两天的销售量总是不同的,即a i -1≠a i。注意,如果两天不相邻,销售量可能相同。
输入格式
  输入的第一行包含一个整数n。
  第二行包含n个整数,用空格分隔,分别表示a 1, a 2, …, a n。
输出格式
  输出一个整数,表示折点出现的数量。
样例输入
7
5 4 1 2 3 6 4
样例输出
2
评测用例规模与约定
  所有评测用例满足:1 ≤ n ≤ 1000,每天的销售量是不超过10000的非负整数。

问题链接CCF201604-1 折点计数
问题简述:(略)
问题分析
重写解题博客以及解题程序代码(参见参考链接),解题逻辑更加清晰,解题代码更加简洁,多种语言解法。
解法一:数组处理
把需要处理的数据读入到程序中的数组里,然后再进行处理,是一种最为常见的做法。每3个数就可以判定是否有折点,n个数需要做n-2次判定。折点有两种,一种是中间点值最大,另外一种是中间点值最小。循环语句for的结束判定尽量不要有表达式,可以避免程序没有进行优化编译时,出现多余的计算。
解法二:输入流处理
如果要求不允许使用数组,则需要使用更高的编程技巧。本来程序的输出是字符流,通过函数scanf()和格式"%d"读入整数,将其转换为整数流,再对整数流进行处理,一边判定折点,一边进行统计。
对输入数据按输入流进行处理,可以不使用数组等变量或只使用简单变量。技巧比较高一些,是职业程序员应该掌握的技巧和解题思路,习惯了也就好了。
解法三:多重流箭头流
这种解法是笔者最早写的题解,被许多人认为难懂,确实是难懂了一些。但是,难懂的东西,往往是因为编程技巧高了一些,过程有点复杂,思路与一般人所想有所不同。
程序说明:(略)
参考链接
CCF201604-1 折点计数(100分)
题记:(略)

100分的C语言程序(解法一:数组处理)如下:

/* CCF201604-1 折点计数 */

#include <stdio.h>

#define N 1000
int a[N];

int main()
{
    int n, i;

    scanf("%d", &n);
    for (i = 0; i < n; i++) scanf("%d", &a[i]); /* 读入数据 */

    /* 判定折点并统计 */
    int cnt = 0;
    for (i = 2; i < n; i++)
        if (a[i - 2] < a[i - 1] && a[i - 1] > a[i]) cnt++;
        else if (a[i - 2] > a[i - 1] && a[i - 1] < a[i]) cnt++;

    printf("%d\\n", cnt); /* 输出结果 */

    return 0;
}

100分的C语言程序(解法二:输入流处理)如下:

/* CCF201604-1 折点计数 */

#include <stdio.h>

int main(void)
{
    int n, left, mid, right, cnt = 0, i;

    scanf("%d%d%d", &n, &left, &mid); /* 读入n,读入前2个数 */
    for ( i = 3; i <= n; i++ ) { /* 读入第3至第n个数 */
        scanf("%d", &right);

        /* 判定折点并统计 */
        if (left < mid && mid > right) cnt++;
        else if (left > mid && mid < right) cnt++;

        left = mid, mid = right;
    }

    printf("%d\\n", cnt); /* 输出结果 */

    return 0;
}

100分的C语言程序(解法三:多重流箭头流)如下:

/* CCF201604-1 折点计数 */

#include <stdio.h>

#define UP 1
#define DOWN 0

int main(void)
{
    int n, first, second, prearrow, arrow, cnt = 0, i;
    scanf("%d%d%d", &n, &first, &second); /* 读入n,读入前2个数 */
    prearrow = second > first ? UP : DOWN; /* 计算箭头方向 */
    first = second;
    for ( i = 3; i <= n; i++ ) { /* 读入第3至第n个数 */
        scanf("%d", &second);
        arrow = second > first ? UP : DOWN; /* 计算箭头方向 */
        if (arrow != prearrow) cnt++; /* 判定折点并统计 */
        prearrow = arrow;
        first = second;
    }
    printf("%d\\n", cnt); /* 输出结果 */

    return 0;
}

100分的Python语言程序如下:

100分的Java语言程序如下:

以上是关于CCF201604-1 折点计数(100分)序列处理的主要内容,如果未能解决你的问题,请参考以下文章

CCF CSP 201604-1 折点计数

CCF认证历年试题

CCF 201604-1折点计数 (水题,暴力)

CSP201604-1:折点计数

201604-1 折点计数

201604-1 折点计数 Java