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; }