1073 多选题常见计分法

1073 多选题常见计分法

在这里插入图片描述

思路

提取标准答案串和学生答案字符串:

  • 用一个长度为105的string数组存储所有的标准答案字符串;
  • 用一个长度为1005的string数组来存储所有的学生答案字符串;
  • 每当学生答案字符串读取到 ‘)’ 时,就说明一道题的答案读取完毕了,开始计算该题的选项错误次数以及得分情况(分析原理见下面的详解)

首先明确错误次数是如何计算的,根据题目的案例1可以得知:

  1. 当多选题的标准答案里有这个选项而答题人没选时,该选项错误次数加1;
  2. 当多选题的标准答案里没有这个选项而答题人选了,该选项错误次数也加1;

创建一个[105][5]大小的int数组error,来存储每道题每个选项的错误次数。判断答题人答案的时候,在循环选项时就可以简单地区分为四种情况:

  1. 答案有-答题人没有:选项错误次数+1。漏选
  2. 答案无-答题人有:选项错误次数+1。错选
  3. 答案有-答题人也有:选项正确。
  4. 答案无-答题人也无:无事发生。

用一个flag来记录该题的情况,选项正确flag就加1,漏选不改变flag,错选的话flag就等于-99。计算学生分数时:

  1. 假如flag正好等于答案字符串的长度,那么拿全部分数。
  2. 假如flag大于0但是小于答案字符串的长度,那么拿一半的分数。
  3. 假如flag小于0,则不拿分。

输出环节:

  1. 依次输出学生的分数
  2. 循环一遍error数组,找出错误次数的最大值。
  3. 若最大值不为0,就再循环一遍error数组,把错误次数为最大值的选项全部输出(这时候按照顺序输出正好符合题目的要求)
  4. 假如错误次数最大值为0,那么就输出too simple
#include<stdio.h>
#include<iostream>
#include<string>

using namespace std;

int score[105];     // 存储每道题的分值
string question[105];  // 存储标准答案字符串
string student[1005];  // 存储学生字符串
double student_score[1005];
int error[105][5];  // 存储每道题每个选项错误次数

int main(void) {
	int n, m; cin >> n >> m;  // n:学生人数, m:题目数量
	for (int i = 0; i < m; i++) {
		cin >> score[i];
		int r, t; cin >> r >> t;  // r:选项个数, t:正确选项个数
		for (int j = 0; j < t; j++) {
			string x; cin >> x;  // 读取每个正确选项
			question[i] += x;    // 构成标准答案字符串
		}
	}

	getchar();   // 前面用的是cin,会在上面留下一个换行符,需要读取掉
	for (int i = 0; i < n; i++) {
		string s;  // 存储整行的答案
		getline(cin, s);
		string temp;  // 存储每道题的答案
		int index = 0;  // 记录题号
		for (int j = 0; j < s.size(); j++) {
			if (s[j] >= 'a' && s[j] <= 'z') { temp += s[j]; }
			int flag = 0;	// 记录这道题答题情况
			if (s[j] == ')') {  // 说明一道题结束
				for (int k = 0; k < 5; k++) {  // 根据标准答案和学生答案中能否找到abcde这些选项来判断
					if (question[index].find('a' + k) == -1 && temp.find('a' + k) == -1) { continue; }
					if (question[index].find('a' + k) != -1 && temp.find('a' + k) != -1) { flag++; }
					if (question[index].find('a' + k) != -1 && temp.find('a' + k) == -1) { error[index][k]++; }
					if (question[index].find('a' + k) == -1 && temp.find('a' + k) != -1) { error[index][k]++; flag = -99; }
				}

				if (flag > 0 && flag != question[index].size()) { // 有漏选
					student_score[i] += score[index] / 2.0;
				}
				if (flag > 0 && flag == question[index].size()) { // 全对
					student_score[i] += score[index];
				}

				index++;
				temp.clear();
			}
		}
	}

	// 输出学生的分数
	for (int i = 0; i < n; i++) {
		printf("%.1f\n", student_score[i]);
	}

	int errorMax = 0; // 存储最大错误次数
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < 5; j++) {
			if (error[i][j] > errorMax) { errorMax = error[i][j]; }
		}
	}

	if (errorMax > 0) {
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < 5; j++) {
				if (error[i][j] == errorMax) {
					printf("%d %d-%c\n", errorMax, i + 1, 'a' + j);
				}
			}
		}
	}
	else {
		cout << "Too simple";
	}


	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值