题目地址:1073.多选题常见计分方法
易错分析:漏选和错选都算错,不要忽略任意一种
求解过程:本文用set的count方法来确定学生的输入选项是否在正确答案中,用迭代器遍历正确答案,在用count方法来确定是否有选项漏掉。把这些错误的选项都存在一个数组WrongMat中,最后通过遍历的WrongMat来输出错误的选项结果。
程序:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <set>
using namespace std;
struct Q
{
int RightNum; // 正确的选项数
int ChooseNum; // 总的选项数
int Grade; // 总分
set <char> s; // 保存每一个问题的正确答案
};
int main(int argc, char const *argv[])
{
int N, M, ChooseNumStu, wrongMax = 0, AllRight = 0;
char awr; // 选项
scanf("%d %d", &N, &M);
int wrongMat[M][5];
memset(wrongMat, 0, sizeof(wrongMat)); // 初始化为0
Q q[M];
for (int i = 0; i < M; i++) // 输入每一题的信息
{
scanf("%d %d %d", &q[i].Grade, &q[i].ChooseNum, &q[i].RightNum);
for (int k = 0; k < q[i].RightNum; k++)
{
scanf(" %c", &awr);
q[i].s.insert(awr); // 把正确答案存入集合
}
}
getchar(); // 挡掉回车
for (int i = 0; i < N; i++)
{
double sum = 0; // 学生总成绩
for (int j = 0; j < M; j++)
{
set <char> Answer;
set <char>:: iterator it;
int flag = 0; // 记录学生是否有错选,1表示有错选
scanf("(%d", &ChooseNumStu);
for (int k = 0; k < ChooseNumStu; k++)
{
scanf(" %c", &awr);
Answer.insert(awr);
if (!q[j].s.count(awr)) // 如果该答案不在集合中
{
wrongMat[j][awr-'a']++; // 'a' - 'a' = 0;
if (wrongMat[j][awr - 'a'] > wrongMax)
wrongMax = wrongMat[j][awr - 'a'];
flag = 1;
}
}
for (it = q[j].s.begin(); it != q[j].s.end(); it++)
{
if (!Answer.count(*it)) // 如果答案漏选了
{
AllRight = 1; // 为1表示不是所有人都做对
wrongMat[j][*it-'a']++;
if (wrongMat[j][*it - 'a'] > wrongMax)
wrongMax = wrongMat[j][*it - 'a'];
}
}
scanf(")");
getchar(); // 吃掉空格
if (!flag) // 如果不存在错选情况
{
if (Answer == q[j].s) // 如果选项一样
sum += q[j].Grade;
else
{
sum += 0.5 * q[j].Grade;
AllRight = 1;
}
}
}
printf("%0.1lf\n", sum);
}
if (!AllRight) // 如果没人犯错
printf("Too simple\n");
else
{
for (int i = 0; i < M; i++)
for (int j = 0; j < 5; j++)
if (wrongMat[i][j] == wrongMax)
printf("%d %d-%c\n", wrongMax, i+1, j+'a');
}
return 0;
}