批改多选题是比较麻烦的事情,有很多不同的计分方法。有一种最常见的计分方法是:如果考生选择了部分正确选项,并且没有选择任何错误选项,则得到 50% 分数;如果考生选择了任何一个错误的选项,则不能得分。本题就请你写个程序帮助老师批改多选题,并且指出哪道题的哪个选项错的人最多。
输入格式:
输入在第一行给出两个正整数 N(≤1000)和 M(≤100),分别是学生人数和多选题的个数。随后 M 行,每行顺次给出一道题的满分值(不超过 5 的正整数)、选项个数(不少于 2 且不超过 5 的正整数)、正确选项个数(不超过选项个数的正整数)、所有正确选项。注意每题的选项从小写英文字母 a 开始顺次排列。各项间以 1 个空格分隔。最后 N 行,每行给出一个学生的答题情况,其每题答案格式为 (选中的选项个数 选项1 ……)
,按题目顺序给出。注意:题目保证学生的答题情况是合法的,即不存在选中的选项数超过实际选项数的情况。
输出格式:
按照输入的顺序给出每个学生的得分,每个分数占一行,输出小数点后 1 位。最后输出错得最多的题目选项的信息,格式为:错误次数 题目编号(题目按照输入的顺序从1开始编号)-选项号
。如果有并列,则每行一个选项,按题目编号递增顺序输出;再并列则按选项号递增顺序输出。行首尾不得有多余空格。如果所有题目都没有人错,则在最后一行输出 Too simple
。
输入样例 1:
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) (3 b d e) (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) (1 c) (4 a b c d)
输出样例 1:
3.5
6.0
2.5
2 2-e
2 3-a
2 3-b
输入样例 2:
2 2
3 4 2 a c
2 5 1 b
(2 a c) (1 b)
(2 a c) (1 b)
输出样例 2:
5.0
5.0
Too simple
思路: 这题是之前1058那道题的改编
直接开ASCII数组, 像下面这样
arr['a'], arr['b'], arr['c'], arr['d'], arr['e']
一个数组用来存储正确的答案, 一个用来存储学生的答案.
1) 完全正确, 全部选项匹配才能完全正确
2) 错误, 学生选了这个选项, 也就是响应的某项标记1, 而正确答案没有
这项, 则该题错误
3) 部分正确, 余下的的用else, 也就是部分正确的情况
#include <stdio.h>
struct s_ques {
int qscore; // 满分
int qsnum; // 选项个数
int qrnum; // 正确选项个数
int qawr[128]; // 所有正确选项
};
#define LEN 120
int main (void) {
int snum; // 学生人数
int qnum; // 题目个数
s_ques ques[LEN]; // 每道题的信息
int wrong[LEN][128] = {0}; // 错误信息矩阵
int wmax = 0; // 最大错误次数
char ch;
int i;
int j;
int k;
scanf("%d %d", &snum, &qnum);
for (i = 1; i <= qnum; i++) {
ques[i].qawr['a'] = 0;
ques[i].qawr['b'] = 0;
ques[i].qawr['c'] = 0;
ques[i].qawr['d'] = 0;
ques[i].qawr['e'] = 0;
scanf("%d %d %d", &ques[i].qscore, &ques[i].qsnum, &ques[i].qrnum);
for (j = 1; j <= ques[i].qrnum; j++) {
scanf(" %c", &ch);
ques[i].qawr[ch] = 1;
}
}
getchar(); // 回车挡掉
int len; // 初始是第1道题
int mys; // 这个学生选了几个选项
char slt; // 选中选项
for (i = 1; i <= snum; i++) {
double score = 0.0; // 每个学生的初始分数
len = 1;
// 一个 while 循环是一位学生答题的全部情况
while ((ch = getchar()) != '\n') {
if (ch == '(') {
int cawr[128] = {0}; // 用来记录该题答题情况, 有1, 无0
scanf("%d", &mys);
for (j = 1; j <= mys; j++) {
scanf(" %c", &slt);
cawr[slt] = 1;
}
// 学生这个选项答了, 而正确答案没有, 相应错误+1
for (k = 'a'; k <= 'e'; k++) {
if (cawr[k] != ques[len].qawr[k]) wrong[len][k]++;
if (wrong[len][k] > wmax) wmax = wrong[len][k];
}
if (
// 所有选项全部匹配, 为完全正确
cawr['a'] == ques[len].qawr['a'] &&
cawr['b'] == ques[len].qawr['b'] &&
cawr['c'] == ques[len].qawr['c'] &&
cawr['d'] == ques[len].qawr['d'] &&
cawr['e'] == ques[len].qawr['e']
) {
score += (double)(ques[len].qscore);
} else if (
// 这一项学生答了, 而正确答案没有这一项, 该题答错
(cawr['a'] == 1 && ques[len].qawr['a'] == 0) ||
(cawr['b'] == 1 && ques[len].qawr['b'] == 0) ||
(cawr['c'] == 1 && ques[len].qawr['c'] == 0) ||
(cawr['d'] == 1 && ques[len].qawr['d'] == 0) ||
(cawr['e'] == 1 && ques[len].qawr['e'] == 0)
) {
// 该题答错
// do nothing
} else {
// 部分正确
score += (double)(ques[len].qscore) / 2.0;
}
len++; // 进入到下一题
}
}
printf("%.1f\n", score); // 打印这位同学的得分
}
if (wmax == 0) {
printf("Too simple\n");
} else {
for (i = 1; i <= qnum; i++) {
for (j = 'a'; j <= 'e'; j++) {
if (wrong[i][j] == wmax) {
printf("%d %d-%c\n", wrong[i][j], i, j);
}
}
}
}
return 0;
}
这道题跟1058有些相似,可以直接把代码搬过来改一下,这里我在结构体中增加了一个变量ncount[101](记录各题的错误次数),单独写了一个函数(比较正确选项与输入选项,同时更新ncount,返回该题得分),输出也一样,我们可以先找最大值,如果最大值存在,将与它相等的选项输出就行。
#include<iostream>
#include<string>
#include<cmath>
using namespace std;
struct number {
double mark;
int nc;
int ny;
int ncount[101] = {0}; //用于记录每个选项错误次数
int pd[101] = { 0 };
}s[101];
double judge(int a[100], int b[100] ,int k) { //a为正确选项,b为输入选项
int count = 0; //正确计数器
int yn = 0; //0为答对,1为答错
for (int i = 0; i < s[k].nc; i++) {
if (b[i] && a[i]) { //如果输入为正确,正确计数器+1
count++;
}
else if (a[i] && !b[i]) { //没有输入的正确选项
s[k].ncount[i]++;
}
else if (!a[i] && b[i]) { //输入了一个错误的选项
s[k].ncount[i]++;
yn = 1;
}
}
if (yn)
return 0;
else if (count != s[k].ny) //部分正确
return s[k].mark / 2;
else if (count == s[k].ny) //全部正确
return s[k].mark; //返回得分
}
int main() {
int n, m, k;
double sum;
char ch;
int t[101]; //用t记录输入的选项
cin >> n >> m;
for (int i = 0; i < m; i++) {
cin >> s[i].mark >> s[i].nc >> s[i].ny;
for (int j = 0; j < s[i].ny; j++) {
cin >> ch;
s[i].pd[ch - 'a'] = 1;
}
}
for (int i = 0; i < n; i++) {
sum = 0;
for (int j = 0; j < m; j++) {
cin >> ch >> k;
for (int i = 0; i < 101; i++) t[i] = 0; //t置为空
for (int h = 0; h < k; h++) {
cin >> ch;
t[ch - 'a']++;
}
sum+=judge(s[j].pd, t,j);
cin >> ch;
}
printf("%0.1lf\n", sum);
}
int max = 0;
for (int i = 0; i < m; i++) { //寻找最大值
for (int j = 0; j < s[i].nc; j++)
max = s[i].ncount[j] > max ? s[i].ncount[j] : max;
}
if (max) { //存在最大值(即有错题)
for (int i = 0; i < m; i++) {
for (int j = 0; j < s[i].nc; j++)
if (s[i].ncount[j] == max) {
cout << max << " " << i + 1 << "-" << (char)(j + 'a') << endl;
}
}
}
else
cout << "Too simple";
return 0;
}