「PAT乙级真题解析」Basic Level 1003 我要通过! (问题分析+完整步骤+伪代码描述+提交通过代码)

题设要求根据给定的三条标准, 检查输入的文本是否正确, 正确则输出"YES", 不正确则输出"NO". 所以核心就是如果将题设给定的三个判断条件明确成编程语言的if条件.

#算法#pat考试#数据结构#需求分析#c语言

Table of Contents

乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范。从小白开始逐步掌握用编程解决问题。

PAT (Basic Level) Practice 1003 我要通过!

问题分析

题设要求根据给定的三条标准, 检查输入的文本是否正确, 正确则输出"YES", 不正确则输出"NO". 所以核心就是如果将题设给定的三个判断条件明确成编程语言的if条件.

标准一

不可以含有PAT之外的字符.

  • for char in input_content:
    • if char != 'P' and char != 'A' and char != 'T': return False

标准二

符合格式xPATx的字符串应该判断为正确, x可以是空字符串或者仅由字母A组成的字符串。 可以对应为同时满足以下条件:

  • 字符串中只有一个P和一个T
  • 字符P在字符T前面
  • 字符P和字符T中间有一个A
  • 字符P前的A和字符T后的A个数相同

比如:

  • PAT
  • APATA
  • AAPATAA

标准三

如果 aPbTc 是正确的,那么 aPbATca也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串 这个条件可以转述为: 在正确的答案中, 在中间的A和末尾的A增加相同数量的A之后仍然是正确的 而标准二给出了最基础的正确答案: PAT, APATA, AAPATAA, ... 这意味着, 假设首部的A, 中间的A以及末尾的A个数分别为a, b, c. 则, 按照标准二的正确答案, 中间的A减到1个, 末尾的A减去(中间减掉的个数*首部A的个数)之后, 首部的A与末尾的A个数应该一致。 比如: "AAPAATAAAA" ---(中间减去1个A, 末尾减去 1 * 2个A)---> "AAPATAA"(标准二给出的正确答案) 即, 满足表达式: a = c - (b - 1) * a, 等价变换为: a * b = c

标准对应的判断条件总结

  1. 如果有P, A, T之外的字符: False
  2. 如果P的个数不等1: False
  3. 如果T的个数不等1: False
  4. 如果P不在T前面: False
  5. 如果中间的A个数等于0: False
  6. 如果首部A的个数 * 中间A的个数不等于末尾A的个数: False
  7. 其余情况: True

完整描述流程

  1. 获取输入: 需要检查的文本数目
  2. 对于每一个文本:
    • 获取输入: 文本
    • 初始化统计器:
      • P的个数 = 0;
      • T的个数 = 0;
      • 首部A的个数 = 0;
      • 中间A的个数 = 0;
      • 末尾A的个数 = 0;
    • 对于文本中的每一个字符:
      • 如果不是PAT, 判为答案错误, 输出"NO"
      • 如果是T且当前P的个数为0, 判为答案错误, 输出"NO"
      • 如果是T, T的个数++;
      • 如果是P, P的个数++;
      • 如果是A且当前P的个数为0, 首部A的个数++;
      • 如果是A且当前P的个数为1且当前T的个数为0, 中间A的个数++;
      • 如果是A且当前T的个数为1, 末尾A的个数++;
    • 如果P的个数不等于1 或 T的个数不等于1: 判为答案错误, 输出"NO"
    • 如果中间A的个数为0: 判为答案错误, 输出"NO"
    • 如果首部A的个数 * 中间A的个数 不等于 末尾A的个数: 判为答案错误, 输出"NO"
    • 其余情况, 判为答案正确, 输出"YES"

伪代码描述

  1. get input: case_amount
  2. for each case:
    • get input: content

    • init recorder:

      • amount_P = 0;
      • amount_T = 0;
      • amount_A_at_header = 0;
      • amount_A_in_middle = 0;
      • amount_A_at_tail = 0;
      • answer_is_correct = True;
    • for char in content:

      • if char != 'P' and char != 'T' and char != 'A':
        • answer_is_correct = False;
        • break;
      • if char == 'T' and amount_P == 0:
        • answer_is_correct = False;
        • break;
      • if char == 'T': amount_T++;
      • if char == 'P': amount_T++;
      • if char == 'A' and amount_P == 0: amount_A_at_header++;
      • if char == 'A' and amount_P == 1 and amount_T == 0: amount_A_at_header++;
      • if char == 'A' and amount_T == 1: amount_A_at_tail++;
    • if amount_P != 1 or amount_T != 1:

      • answer_is_correct = False
    • if amount_A_in_middle == 0:

      • answer_is_correct = False;
    • if amount_A_at_header * amount_A_in_middle != amount_A_at_tail:

      • answer_is_correct = False
    • if answer_is_correct == True:

      • print("YES");
    • else:

      • print("NO");

完整提交代码

/*
# 问题分析
题设要求根据给定的三条标准, 检查输入的文本是否正确, 正确则输出"YES", 不正确则输出"NO".
所以核心就是如果将题设给定的三个判断条件明确成编程语言的if条件.
 
## 标准一
不可以含有`P`、`A`、`T`之外的字符.
- for char in input_content:
    - if char != 'P' and char != 'A' and char != 'T': return False
 
## 标准二
符合格式`xPATx`的字符串应该判断为正确, `x`可以是空字符串或者仅由字母`A`组成的字符串。
可以对应为同时满足以下条件:
- 字符串中只有一个`P`和一个`T`
- 字符`P`在字符`T`前面
- 字符`P`和字符`T`中间有一个`A`
- 字符`P`前的`A`和字符`T`后的`A`个数相同
 
比如:
- `PAT`
- `APATA`
- `AAPATAA`
 
## 标准三
如果 `aPbTc` 是正确的,那么 `aPbATca`也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串
这个条件可以转述为: **在正确的答案中, 在中间的A和末尾的A增加相同数量的A之后仍然是正确的**
而标准二给出了最基础的正确答案: `PAT`, `APATA`, `AAPATAA`, ...
这意味着, 假设首部的A, 中间的A以及末尾的A个数分别为a, b, c.
则, 按照标准二的正确答案, 中间的A减到1个, 末尾的A减去(中间减掉的个数*首部A的个数)之后, 首部的A与末尾的A个数应该一致。
比如: "AAPAATAAAA" ---(中间减去1个A, 末尾减去 1 * 2个A)---> "AAPATAA"(标准二给出的正确答案)
即, 满足表达式: a = c - (b - 1) * a, 等价变换为: a * b = c
 
## 标准对应的判断条件总结
1. 如果有`P`, `A`, `T`之外的字符: False
2. 如果`P`的个数不等1: False
3. 如果`T`的个数不等1: False
4. 如果`P`不在`T`前面: False
5. 如果`中间的A`个数等于0: False
6. 如果`首部A`的个数 * `中间A`的个数不等于`末尾A`的个数: False
7. 其余情况: True
 
# 完整描述流程
1. 获取输入: 需要检查的文本数目
2. 对于每一个文本:
    - 获取输入: 文本
    - 初始化统计器:
        - P的个数 = 0;
        - T的个数 = 0;
        - 首部A的个数 = 0;
        - 中间A的个数 = 0;
        - 末尾A的个数 = 0;
    - 对于文本中的每一个字符:
        - 如果不是`P`或`A`或`T`, 判为答案错误, 输出"NO"
        - 如果是`T`且当前P的个数为0, 判为答案错误, 输出"NO"
        - 如果是`T`, T的个数++;
        - 如果是`P`, P的个数++;
        - 如果是`A`且当前P的个数为0, 首部A的个数++;
        - 如果是`A`且当前P的个数为1且当前T的个数为0, 中间A的个数++;
        - 如果是`A`且当前T的个数为1, 末尾A的个数++;
    - 如果P的个数不等于1 或 T的个数不等于1: 判为答案错误, 输出"NO"
    - 如果中间A的个数为0: 判为答案错误, 输出"NO"
    - 如果首部A的个数 * 中间A的个数 不等于 末尾A的个数: 判为答案错误, 输出"NO"
    - 其余情况, 判为答案正确, 输出"YES"
 
# 伪代码描述
1. get input: case_amount
2. for each case:
    - get input: content
    - init recorder:
        - amount_P = 0;
        - amount_T = 0;
        - amount_A_at_header = 0;
        - amount_A_in_middle = 0;
        - amount_A_at_tail = 0;
        - answer_is_correct = True;
    - for char in content:
        - if char != 'P' and char != 'T' and char != 'A':
            - answer_is_correct = False;
            - break;
        - if char == 'T' and amount_P == 0:
            - answer_is_correct = False;
            - break;
        - if char == 'T': amount_T++;
        - if char == 'P': amount_T++;
        - if char == 'A' and amount_P == 0: amount_A_at_header++;
        - if char == 'A' and amount_P == 1 and amount_T == 0: amount_A_at_header++;
        - if char == 'A' and amount_T == 1: amount_A_at_tail++;
 
    - if amount_P != 1 or amount_T != 1:
        - answer_is_correct = False
    - if amount_A_in_middle == 0:
        - answer_is_correct = False;
    - if amount_A_at_header * amount_A_in_middle != amount_A_at_tail:
        - answer_is_correct = False
 
    - if answer_is_correct == True:
        - print("YES");
    - else:
        - print("NO");
 
*/
 
 
# include<stdio.h>
 
 
int check_content_is_correct(char* content){
    int amount_P = 0;
    int amount_T = 0;
    int amount_A_at_header = 0;
    int amount_A_in_middle = 0;
    int amount_A_at_tail = 0;
 
    for (int i = 0; content[i]; i++){
        if (content[i] == 'T' && amount_P == 0) return 0;
        if (content[i] == 'T'){
            amount_T++;
        } else if (content[i] == 'P'){
            amount_P++;
        } else if (content[i] == 'A'){
            if (amount_P == 0){
                amount_A_at_header++;
            } else if (amount_P == 1 && amount_T == 0){
                amount_A_in_middle++;
            } else if (amount_T == 1){
                amount_A_at_tail++;
            }
        } else {
            return 0;
        }
    }
 
    if (amount_P != 1 || amount_T != 1) return 0;
    if (amount_A_in_middle == 0) return 0;
    if (amount_A_at_header * amount_A_in_middle != amount_A_at_tail) return 0;
 
    return 1;
}
 
 
 
int main(){
    int case_amount;
    scanf("%d", &case_amount);
    
    char content[101];
    for(int i = 0; i < case_amount; i++){
        scanf("%s", content);
        int result = check_content_is_correct(content);
        if (result == 1){
            printf("YES\n");
        } else {
            printf("NO\n");
        }
    }
    return 0;
}
「PAT乙级真题解析」Basic Level 1003 我要通过! (问题分析+完整步骤+伪代码描述+提交通过代码) | 生活糖果