[蓝蓝计算机考研算法训练二期]-day03

185 阅读3分钟

4、一个小球从10m处落下,每次的弹回之前的一半,请问小球在静止之前一共走过多少距离。

思路

以落下、弹起为一个轮回,累加下落时的高度和弹起时的高度来计算总的结果。

具体实现

#include <stdio.h>

int main() {
    float height = 10.0;  // 初始高度
    float distance = 0.0; // 总共走过的距离

    // 循环计算小球弹起和落下的过程
    while (height != 0.0) {    // 当小球回弹高度为0时停止运动
        distance += height;    // 累加落下的距离
        height /= 2.0;         // 计算弹起的高度
        distance += height;    // 累加弹起的距离
    }

    printf("小球在静止之前一共走过 %.2f 米\n", distance);

    return 0;
}

image.png

5、我要通过!

答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于PAT的“答案正确”大派送————只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。

得到“答案正确”的条件是:

1.字符串中必须仅有P、A、T这三种字符,不可以包含其他字符;

2.任意形如xPATx的字符串都可以获得“答案正确”,其中x或者是空字符串,或者是仅由字符A组成的字符串。

3.如果aPbTc是正确的,那么aPbATca也是正确的,其中a、b、c均或者是空字符串,或者是仅由字母A组成的字符串。

现在就请你为PAT写一个自动裁判程序,判定那些字符串可以是获得“答案正确”的。

输入格式

每个测试输入包含一个测试用例。第1行给出一个正整数n(\leqslant10),是需要检测的字符串个数。接下来每个字符串占一行,如果盖子谷川可以获得“答案正确”,则输出YES,否则输出NO

输出样例:

10
PAT
PAAT
AAPATAA
AAPAATAAAA
xPATx
Whatever
APAAATAA
APT
APAATTAA

输出样例:

YES
YES
YES
YES
NO
NO
NO
NO
NO
NO

思路

首先理解本题大意:对于给定的字符串,

  • 其中必须有且只能有一个“T”和一个“P”,且只能有“T”、“A”和“P”三种字符
  • 可以为“xTAPx”,其中,x为空或者任意多个“A”,且前后两个x相同
  • 如果“aPbTc”满足了上述情况,则aPbATca也是“答案正确”,abc类似上述的x,其中有隐含条件即:PAT为“答案正确”,则PAAT也为“答案正确”,同理,PAAT等都为“答案正确”,所以在判断时不能单纯地认为“P”和“T”中间只有一个“A”

解题思路就是根据要求来一个一个排除不合适的字符串:

  • 有2个以上的“P”,或者“T”不符合
  • 有除了“P”、“A”和“T”以外的字符不符合
  • 没有出现过“P”和“T”的不符合
  • “P”和“T”没有依次出现,即“A”在“P”前面,或者“P”和“T”中间没有“A”的不符合
  • 不符合“xPATx”的,不符合
  • “aPbTc”正确时,不符合“aPbATca”的不符合

具体实现

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

// 判断字符串是否符合条件
int is_valid(char str[])
{
    int p_pos = -1, t_pos = -1, i;
    int len = strlen(str);
    int count_p = 0, count_t = 0;

    // 遍历字符串
    for (i = 0; i < len; i++) {
        if (str[i] == 'P') {
            // 如果之前已经出现过P,就返回NO
            if (count_p > 0)
                return 0;
            p_pos = i;
            count_p++;
        } else if (str[i] == 'T') {
            // 如果之前已经出现过T,就返回NO
            if (count_t > 0)
                return 0;
            t_pos = i;
            count_t++;
        } else if (str[i] != 'A') {
            // 如果出现了其他字符,就返回NO
            return 0;
        }
    }

    // 如果没有出现P或T,就返回NO
    if (p_pos == -1 || t_pos == -1)
        return 0;

    // 如果P和T之间没有A,就返回NO
    if (t_pos - p_pos <= 1)
        return 0;

    // 如果最后一个T后面还有A,就返回NO
    // 即判断是否是aPbTc的形式,如果T后的A比P前的A少,则一定不符合条件 
    if (len - t_pos - 1 < p_pos * (t_pos - p_pos - 1))
        return 0;

    // 判断xPATx的形式
    if (p_pos * (t_pos - p_pos - 1) == len - t_pos - 1)
        return 1;

    // 判断aPbTc和aPbATca的形式
    int a_len = p_pos;
    int b_len = t_pos - p_pos - 1;
    int c_len = len - t_pos - 1 - a_len;
    if (a_len * b_len == c_len)
        return 1;

    // 不符合任何形式,返回NO
    return 0;
}

int main()
{
    int n, i;		// 分别计数字符串个数和循环次数 
    char str[101];

    scanf("%d", &n);	// 读入字符串个数

    // 循环读入字符串并判断
    for (i = 0; i < n; i++) {
        scanf("%s", str);
        if (is_valid(str)) {
            printf("YES\n");
        } else {
            printf("NO\n");
        }
    }

    return 0;
}

image.png

小结

今天的算法第二题略有难度,需要考虑的情况种类很多,特别是“P”和“T”中间不能想当然地认为是只有一个“A”才符合条件,同时也需要大量的时间来进行调试。因为昨天学了一点代码规范,所以在今天的代码风格,笔者自认为还是更加清晰一点的,加油!