PAT乙级(二)(1003-1005)

1003

“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。
得到“答案正确”的条件是:
字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符;
任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;
如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串。
现在就请你为 PAT 写一个自动裁判程序,判定哪些字符串是可以获得“答案正确”的。

下面这段代码用例测试正确,PAT系统判断部分正确,尚未知晓原因。

#include <iostream>
#include <cstdio>
#include <string>
#include <stack>
#include <queue>

using namespace std;

int judge(string sr){
    string sr_copy = sr;
    int mid_A_count_sub_1 = 0;
    bool P_flag = true;
    bool A_head_flag = true;
    bool A_mid_flag = false;
    bool A_rear_flag = false;
    bool T_flag = true;
    int A_head = 0;
    int A_mid = 0;
    int A_rear = 0;
    for(int i=0;i<sr.length();i++){
        if (sr[i] == 'A'){
            if(A_head_flag){
                A_head++;
            }
            if(A_mid_flag){
                A_mid++;
            }
            if(A_rear_flag){
                A_rear++;
            }
        }
        else if(sr[i] == 'P'){
            if (!P_flag){return 0;}
            P_flag = false;
            A_head_flag = false;
            A_mid_flag = true;
        }
        else if(sr[i] == 'T'){
            if (!T_flag){return 0;}
            T_flag = false;
            A_mid_flag = false;
            A_rear_flag = true;
        }
        else {return 0;}
    }
    if (A_mid != 0 ){
        if (A_head*A_mid == A_rear){return 1;}
        else{return 0;}
    }
    else {return 0;}
}

int main()
{
    string sr;
    int loop;
    cin>>loop;
    queue <int> que;
    for (int i=0;i<loop;i++){
        cin>>sr;
        que.push(judge(sr));
    }
    while(!que.empty()){
        if (que.front()){
            cout<<"YES"<<endl;
        }
        else{cout<<"NO"<<endl;}
        que.pop();
    }
    return 0;
}


下面这段代码PAT系统显示正确,但系统对于 PPAT这个用例的测试是显示正确。
根据题目描述,PPAT应该是错误的。
代码来自 https://www.bilibili.com/video/av75899292

#include <iostream>
#include <cstdio>
#include <string>
#include <stack>
#include <queue>

using namespace std;

//int judge(string sr){}

int main()
{
    int N,P,T,bef,mid,aft;
    cin>>N;
    string tmp;
    while(N--){
        cin>>tmp;
        bool is = true;
        int vali[3] = {0};
        for(int i=0;i<tmp.length();i++){
            if(tmp[i] == 'P') vali[0] = 1;
            if(tmp[i] == 'A') vali[1] = 1;
            if(tmp[i] == 'T') vali[2] = 1;
        }
        for(int i=0;i<tmp.length();i++){
            if(tmp[i]!='P'&&tmp[i]!='A'&&tmp[i]!='T'){
                is = false;
                break;
            }
        }
        if (vali[0]!=1||vali[1]!=1||vali[2]!=1){
            is = false;
        }
        P = tmp.find('P');
        T = tmp.find('T');
        if(P==tmp.npos||T==tmp.npos){
            is = false;
        }
        bef = P;mid = T-P-1;aft = tmp.length()-T-1;
        if (aft!=bef*mid){
            is = false;
        }
        if (is){cout<<"YES"<<endl;}
        else {cout<<"NO"<<endl;}
    }
}

在这里插入图片描述
下面给出一种没有任何问题的代码,但我在最后的if中删去了 T-P!=1,仍正确。
代码来自https://blog.csdn.net/liuchuo/article/details/51994881


#include <iostream>
#include <map>
using namespace std;
int main() {
    int n, p = 0, t = 0;
    string s;
    cin >> n;
    for(int i = 0; i < n; i++) {
        cin >> s;
        map<char, int> m;
        for(int j = 0; j < s.size(); j++) {
            m[s[j]]++;
            if (s[j] == 'P') p = j;
            if (s[j] == 'T') t = j;
        }
        if (m['P'] == 1 && m['A'] != 0 && m['T'] == 1 && m.size() == 3 && p * (t-p-1) == s.length()-t-1)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

总结陈词

1、判断一个字符串是否只包含3种,可以参照第二组代码实现。第一步,先确定只有这3种存在。二步,判断每一种都在(利用一个标志数组实现)。
2、函数string.find(‘A’),返回A在母串种的位置,返回类型int。如果找不到在,则返回string.npos(一个Int型,表示字符串长度+1),查找字符串a是否包含子串b,不是用strA.find(strB) > 0 而是 strA.find(strB) != string:npos。
3、map红黑树。C++中map提供的是一种键值对容器,里面的数据都是成对出现的,如下图:每一对中的第一个值称之为关键字(key),每个关键字只能在map中出现一次;第二个称之为该关键字的对应值。
map详细见:https://blog.csdn.net/google19890102/article/details/51720305

1004

读入 n(>0)名学生的姓名、学号、成绩,分别输出成绩最高和成绩最低学生的姓名和学号
输入格式:
每个测试输入包含 1 个测试用例,格式为
第 1 行:正整数 n
第 2 行:第 1 个学生的姓名 学号 成绩
第 3 行:第 2 个学生的姓名 学号 成绩
… … …
第 n+1 行:第 n 个学生的姓名 学号 成绩
其中姓名和学号均为不超过 10 个字符的字符串,成绩为 0 到 100 之间的一个整数,这里保证在一组测试用例中没有两个学生的成绩是相同的。
输出格式:
对每个测试用例输出 2 行,第 1 行是成绩最高学生的姓名和学号,第 2 行是成绩最低学生的姓名和学号,字符串间有 1 空格。

此题PAT系统显示部分正确,这种写法没有限制学号和姓名不超过十个字符。

#include <iostream>
#include <cstdio>
#include <string>
#include <stack>
#include <queue>
#include <vector>

using namespace std;

//int judge(string sr){}
struct s{
    string stu_name;
    string stu_id;
    int stu_grade;
}stu;

int main()
{
    int ct;
    cin>>ct;
    vector <string> stu_name;
    vector <string> stu_id;
    vector <int> stu_grade;
    while (ct--){
        cin>>stu.stu_name>>stu.stu_id>>stu.stu_grade;
        stu_name.push_back(stu.stu_name);
        stu_id.push_back(stu.stu_id);
        stu_grade.push_back(stu.stu_grade);
    }
    unsigned int max_grade = 0;
    int max_position = 0;
    unsigned int min_grade = 0;
    int min_position = 0;
    for (int i=0;i<stu_grade.size();i++){
        if (stu_grade[i]>max_grade){
            max_grade = stu_grade[i];
            max_position = i;
        }
        if (stu_grade[i]<min_grade){
            min_grade = stu_grade[i];
            min_position = i;
        }
    }
    cout<<stu_name.at(max_position)<<' '<<stu_id.at(max_position)<<endl;
    cout<<stu_name.at(min_position)<<' '<<stu_id.at(min_position)<<endl;
}

以下是正确写法,代码来自https://blog.csdn.net/qq_43228218/article/details/88404911

#include <iostream>
#include <string>
#include <algorithm>
#define N 1024
using namespace std;
 
struct student{
	char name[11];
	char num[11];
	int score;
}stu[N];
 
bool cmp(const student &a,const student &b){
	return a.score<b.score;
}
 
int main(){
	int n,flag=1;
	while(flag){
		cin >> n;
		if(n>0) flag=0;	
	}
	
	for(int i=0;i<n;i++){
		cin >> stu[i].name >> stu[i].num >> stu[i].score;
	}
	sort(stu,stu+n,cmp);
	cout << stu[n-1].name << " " << stu[n-1].num << endl;
	cout << stu[0].name << " " << stu[0].num << endl;
	return 0;
}


总结陈词

1、主要关注struct的用法。
2、在限制字符数量的题目中,使用char[]字符数组
3、学生的姓名 学号 成绩 其中姓名和学号均为不超过 10 个字符的字符串。
所以在定义字符数组的时候,不能只定义为10,因为字符串末尾自动加了‘\0’,所以是11。

1005

卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂。
当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对 n=3 进行验证的时候,我们需要计算 3、5、8、4、2、1,则当我们对 n=5、8、4、2 进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这 4 个数已经在验证3的时候遇到过了,我们称 5、8、4、2 是被 3“覆盖”的数。我们称一个数列中的某个数 n 为“关键数”,如果 n 不能被数列中的其他数字所覆盖。
现在给定一系列待验证的数字,我们只需要验证其中的几个关键数,就可以不必再重复验证余下的数字。你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。

输入格式:
每个测试输入包含 1 个测试用例,第 1 行给出一个正整数 K (<100),第 2 行给出 K 个互不相同的待验证的正整数 n (1<n≤100)的值,数字间用空格隔开。
输出格式:
每个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用 1 个空格隔开,但一行中最后一个数字后没有空格。

#include <iostream>
#include <cstdio>
#include <string>
#include <stack>
#include <queue>
#include <vector>
#include <list>
#include <algorithm>

using namespace std;


int main()
{
    int ct;
    int num;
    cin>>ct;
    vector <int> num_list;
    vector <int> temp_list;
    vector <int> result_list;
    while(ct--){
        cin>>num;
        num_list.push_back(num);
    }
    for (unsigned int i=0;i<num_list.size();i++){
        int a = num_list[i];
        while(a!=1){
            if (a&1){
                a = (3*a+1)/2;
            }
            else{
                a = a/2;
            }
            temp_list.push_back(a);
        }
    }
    vector<int>::iterator it;
    for (unsigned int k = 0;k<num_list.size();k++){
        for (unsigned int j=0;j<temp_list.size();j++){
            if (num_list[k] == temp_list[j]){break;}
            if (j == temp_list.size()-1){result_list.push_back(num_list[k]);}
        }
    }
    sort(result_list.rbegin(),result_list.rend());
    int flag = 0;
    for(unsigned int i=0;i<result_list.size();i++){
        if(flag){cout<<' ';}
        flag = 1;
        cout<<result_list[i];
    }
}

总结陈词

1、vector list stack queue的使用
2、#include algorithm 下sort函数的使用,对一个vector进行排序,
sort 对给定区间进行排序
stable_sort 对给定区间进行稳定排序
partial_sort 对给定区间部分元素排序
partial_sort_copy 对给定区间部分元素排序并复制
partition 使得符合某个条件的元素放在前面
stable_partition 相对稳定的使得符合某个条件的元素放在前面

例如sort(result_list.rbegin(),result_list.rend());。
具体可参考链接 ——https://blog.csdn.net/qq_30587589/article/details/84098333

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值