PTA basic 1058 选择题 (20 分) c++语言实现(g++)

批改多选题是比较麻烦的事情,本题就请你写个程序帮助老师批改多选题,并且指出哪道题错的人最多。

输入格式:

输入在第一行给出两个正整数 N(≤ 1000)和 M(≤ 100),分别是学生人数和多选题的个数。随后 M 行,每行顺次给出一道题的满分值(不超过 5 的正整数)、选项个数(不少于 2 且不超过 5 的正整数)、正确选项个数(不超过选项个数的正整数)、所有正确选项。注意每题的选项从小写英文字母 a 开始顺次排列。各项间以 1 个空格分隔。最后 N 行,每行给出一个学生的答题情况,其每题答案格式为 (选中的选项个数 选项1 ……),按题目顺序给出。注意:题目保证学生的答题情况是合法的,即不存在选中的选项数超过实际选项数的情况。

输出格式:

按照输入的顺序给出每个学生的得分,每个分数占一行。注意判题时只有选择全部正确才能得到该题的分数。最后一行输出错得最多的题目的错误次数和编号(题目按照输入的顺序从 1 开始编号)。如果有并列,则按编号递增顺序输出。数字间用空格分隔,行首尾不得有多余空格。如果所有题目都没有人错,则在最后一行输出 Too simple

输入样例:

3 4 
3 4 2 a c
2 5 1 b
5 3 2 b c
1 5 4 a b d e
(2 a c) (2 b d) (2 a c) (3 a b e)
(2 a c) (1 b) (2 a b) (4 a b d e)
(2 b d) (1 e) (2 b c) (4 a b c d)
 

输出样例:

3
6
5
2 2 3 4

 

 

测试点1  所有学生答题正确,没有错题要输出"Too simple"

 

解题思路

1.题目本身不难,判断每个学生的答案与对应题号的答案是否即可,统计错题数量然后输出错题信息,我有点想太多了

2.写这个题的时候,假设了输入的学生答案的信息存在干扰

  所以本题参照之前的PTA basic 1052.卖个萌 的 字符串截取 方法, 取出了所有的学生选择题的选项数, 每一个选项

  AC后查了下别人的答案,我的这个做法太多余了,直接把正确答案字符串录入, 然后和学生的答案字符串比较就可以得出答题是否正确

3.说下我这个方法的思路,

  创建 题目类(序号,错误次数,题目分数,选项个数,正确选项个数,正确选项数组)

  通过格式化的输入,录入题目的信息

  循环通过getline()获取每一个学生的答题信息

  依次判断每个学生的答题情况

  进入判题阶段, 先取出每个学生的每一道题 不包括括号的子串, 取出学生在该题目的选项个数,

    如果不符合正确选项个数, 则该题目错误数量+1, 继续下一题,

    如果选项个数正确, 继续取出学生在该题目下选项数组,和正确的选项数组比较, 相等则累加题目分数, 否则该题目错误数量+1, 继续下一题

  判题阶段结束

  取出最大错题数

  如果没有错题输出"Too simple", 有错题 要输出最大错题数和最大错题数相同的题目序号

 

4.比较符合题目要求的做法

  题目录入的时候,正确答案应该录入字符串"正确选项数 选项1 选项2 ...."

  判题阶段,取出学生答题字符串里括号中的内容"答题选项数 选项1 选项2 ...." 和 题目正确答案的字符串 直接比较

  不需要取出每一个字符

 

比较符合题目的AC版本

 

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class question{
public:
    int falseTime;//错误次数
    int fullPt;//题目分数
    string correctAnswer;//正确答案字符串
    question()=default;
    question(int ft,int fp,string ca)
    :falseTime{ft},fullPt{fp},correctAnswer{ca}{};
};
int main(){
    int n,m;//n学生个数  m题目个数
    int fullPt,maxOptNum,scour{0};
    vector<question> questions;
    vector<string> Answers;
    string str,tempstr;
    cin >> n>>m;
    for(int i=0;i<m;i++){
        cin >> fullPt >> maxOptNum;
        cin.ignore();//忽略换行符和空格
        getline(cin,str);
        question newQ{0,fullPt,str};
        questions.push_back(newQ);
    }
    for(int i=0;i<n;i++){//输入学生答题信息的字符串
        getline(cin,str);
        Answers.push_back(str);
    }
    for(int i=0;i<n;i++){//每个学生都进入 判分过程
        scour=0;
        int left{0},right{0},count{0};//分别是左括号位置,右括号位置 左括号开始到右括号之前的字符数量
        int j=0;//当前题目序号
        str=Answers[i];
        while(left<str.size()&&j<m){//如果答案字符串还没到底 或者 题目还没判完
            if(str[left]=='('){//从'('开始取出答案字符串
                right=left;//right从left开始判断
                while(right<str.size()){
                    if(str[right]==')'){//right取到')'为止的前一位
                        tempstr=str.substr(left+1,count-1);//取出答案字符串
                        // 从'('右边一个位置开始取值,此时count计算了'(' 但是还没有加入')'
                        //因此count-1,就是两个括号中间的内容
                        if(tempstr==questions[j].correctAnswer){//答案字符串和题目的正确答案比较
                                scour+=questions[j].fullPt;
                        }else{
                            questions[j].falseTime++;
                        }
                        count=0;//count清零
                        j++;//到下一题
                        break;
                    }
                    count++;
                    right++;
                }
            }
            left++;
        }
        cout<<scour<<endl;
    }
    scour=0;//清零   用于比较题目的错误数
    for(int i=0;i<questions.size();i++){//取得题目大错数最大值
        scour=questions[i].falseTime>scour?questions[i].falseTime:scour;
    }
    if(scour){//有错题 输出错题信息
        cout<<scour;
        for(int i=0;i<questions.size();i++){
            if(questions[i].falseTime==scour)cout<<" "<<i+1;
        }
    }else{
        cout << "Too simple";
    }
    return 0;
}

 

 

 

 

 

取出了每个学生每道题目答题信息的AC版本

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class question{
public:
    int index;//问题序号
    int falseTime;//错误次数
    int fullPt;//题目分数
    int maxOptNum;//选项个数
    int correctOptNum;//正确选项个数
    vector<int> correctOpts;//正确选项
    question()=default;
    question(int i,int ft,int fp,int mon,int con,vector<int>co)
    :index{i},falseTime{ft},fullPt{fp},maxOptNum{mon},correctOptNum{con},correctOpts{co}{};
};

int getFirstNum(string str){
    int res=-1;
    for(int i=0;i<str.size();i++){
        if(str[i]>='1'&&str[i]<='5'){
            res=static_cast<int>(str[i])-static_cast<int>('0');
            break;
        }
    }
    return res;
}
vector<int> getops(string str,int maxops){
    int op;
    vector<int> ops(maxops,0);
    for(int i=0;i<str.size();i++){
        if(str[i]>='a'&&str[i]<='e'){
            op=static_cast<int>(str[i])-static_cast<int>('a');
            ops[op]=1;
        }
    }
    return ops;
}
int main(){
    int n,m;//n学生个数  m题目个数
    int fullPt,maxOptNum,correctOptNum,temp,scour{0},count{0};
    vector<char> tempOps;
    vector<question> questions;//所有问题集合
    vector<string> Answers;//学生答案集合
    string str,tempstr;
    char c;
    cin >> n>>m;
    for(int i=0;i<m;i++){
        cin >> fullPt >> maxOptNum >> correctOptNum;
        vector<int> tempOps(maxOptNum,0);
        for(int j=0;j<correctOptNum;j++){
            cin >> c;
            if(c<='e'&&c>='a'){
                temp=static_cast<int>(c)-static_cast<int>('a');
                tempOps[temp]=1;
            }
        }
        question newQ(i+1,0,fullPt,maxOptNum,correctOptNum,tempOps);
        questions.push_back(newQ);
        tempOps.clear();
    }
    cin.ignore();
    for(int i=0;i<n;i++){//
        getline(cin,str);
        Answers.push_back(str);
    }
    for(int i=0;i<n;i++){//每个学生都进入 判分过程
        scour=0;
        int left{0},right{0};
        int j=0;//判断每一题答题情况
        str=Answers[i];
        while(left<str.size()&&j<m){
            if(str[left]=='('){//从'('开始一道问题的答案字符串
                right=left;//从left开始截取字符串
                while(right<str.size()){//取到')'为止
                    if(str[right]==')'){
                        tempstr=str.substr(left+1,count-1);
                        // 从'('右边一个位置开始取值,此时count计算了'(' 但是还没有加入')'
                        //因此count-1,就是两个括号中间的内容
                        int opNums=getFirstNum(tempstr);//考生选择的选项数
                        if(opNums!=questions[j].correctOptNum){//如果选项数不等于正确选项数 则错误
                            questions[j].falseTime++;
                        }else{//选项数正确 判断选项 是否符合 正确选项
                            if(getops(tempstr,questions[j].maxOptNum)!=questions[j].correctOpts){//不符合则错误
                                questions[j].falseTime++;
                            }else{//都通过则正确 累加题目分数
                                scour+=questions[j].fullPt;
                            }
                        }
                        count=0;
                        j++;
                        break;
                    }
                    count++;
                    right++;
                }
            }
            left++;
        }
        cout<<scour<<endl;
    }
    
    scour=0;
    for(int i=0;i<questions.size();i++){//取得题目大错数最大值
        scour=questions[i].falseTime>scour?questions[i].falseTime:scour;
    }
    if(scour){//有错题 输出错题信息
        cout<<scour;
        for(int i=0;i<questions.size();i++){
            if(questions[i].falseTime==scour)cout<<" "<<questions[i].index;
        }
    }else{
        cout << "Too simple";
    }
    return 0;
}

 

posted @ 2021-05-09 23:56  keiiha  阅读(107)  评论(0编辑  收藏  举报