题目链接:1073 多选题常见计分法
思路
感觉这代码就像一步一步手工搓的,十分冗长。
- 将题目输入一个结构体中,同时在结构体中用一个数组记录选项错误数。
- 输入学生数据,输入字符型时很容易因为没有考虑空格回车而错误,要注意检查调试。
- 用一个数组记录学生选项,与正确选项比对,若学生选择了错误选项,得分归零,选项不全,得分减半,为了保证精确度,在输入题目数据时将满分翻倍,无需转为浮点问题,最后输出学生分数时,再浮点减半。
- 遍历一遍题目,找到最大错误数,若为0则输出Too Simple。
- 再遍历一遍题目,将错误次数与最大错误数相同的选项筛出,将其题号,选项号输入一个新的结构体,对结构体按照题目要求排序后输出。
代码
#include <iostream>
#include <algorithm>
using namespace std;
struct question{
int sc;//分值
int all;//总选项数
int tu;//正确选项数,没用上
int op[5] = {0};//正确选项
int wr[5] = {0};//错题次数
};
struct wrong{
int no1,no2;
};
int cmp(wrong a, wrong b){
if(a.no1 == b.no1) return a.no2 < b.no2;
return a.no1 < b.no1;
}
int main(){
int N, M ,a ,b, score, count = 0, max = 0;
char c = ' ';
cin >> N >> M;
//问题数据输入
question q[M];
for(int i=0;i<M;i++){
scanf("%d %d %d",&q[i].sc, &q[i].all, &q[i].tu);
q[i].sc *= 2;
for(int j=0;j<q[i].tu;j++){
scanf(" %c",&c);
q[i].op[c - 'a'] = 1;
}
}
//学生数据输入、分数计算
getchar();//吸收回车
for(int i=0;i<N;i++){//第i个学生
score = 0;
for(int j=0;j<M;j++){//第j道题
int d[5] = {0};
b = q[j].sc;
getchar();//吸收左括号
scanf("%d",&a);
for(int k=0;k<a;k++){//学生给出的第k个选项
scanf(" %c",&c);
d[c-'a'] = 1;
}
getchar();//吸收右括号
getchar();//吸收空格或回车
for(int k=0;k<5;k++){
if(d[k]!=q[j].op[k]){
q[j].wr[k]++;
if(d[k]>q[j].op[k])b=0;
else if(b) b = q[j].sc / 2;
}
}
score += b;
}
printf("%.1f\n",score/2.0);
}
//错题数量处理段
wrong w[M * 5];
for(int i=0;i<M;i++){
for(int j=0;j<5;j++){
if(q[i].wr[j]>max) max = q[i].wr[j];
}
}
if(!max){
printf("Too simple\n");
return 0;
}
for(int i=0;i<M;i++){
for(int j=0;j<5;j++){
if(q[i].wr[j] == max){
w[count].no1 = i;
w[count++].no2 = j;
}
}
}
sort(w,w+count,cmp);
for(int i=0;i<count;i++){
printf("%d %d-%c\n",max,w[i].no1+1,'a'+w[i].no2);
}
return 0;
}