1058 选择题
思路:
用一个结构体来存储每一道题的分值、答案、错误数,然后用一个列表来存放这些结构体;
这里注意的是,存放答案的string字符串,无论是标准答案还是学生答案,只需要存储字母字符即可,这些空格是不要的。当判断学生答案和标准答案是否匹配的时候,只需要遍历学生答案的每个字符是否能在标准答案里find到,然后再匹配一下两者的长度即可。
坑点:
getline如果放在普通的cin后面使用,会先读取前面剩下的空字符,所以要先用一个getchar把前面的空字符拿掉再用getline
#include<stdio.h>
#include<iostream>
#include<string>
using namespace std;
struct question {
int score; // 分值
string answer; // 答案字符串
int error = 0; // 错误次数
} Q[105];
int student[1005]; // 学生得分
bool check(string s, int t) {
// int k = 0; // 学生的正确的选项个数
for (int i = 0; i < s.size(); i++) {
if (Q[t].answer.find(s[i]) == -1) { // 假如正确答案里没有找到学生的这个选项
return false;
}
}
if (s.size() != Q[t].answer.size()) { return false; }
else { return true; }
}
int main(void) {
int n, k; cin >> n >> k; // n:学生人数 k:多选题的个数
// 3 4 2 a c
for (int i = 0; i < k; i++) {
int r, t; // 选项个数和正确选项个数
string a = ""; // 正确选项字符串
cin >> Q[i].score >> r >> t;
for (int j = 0; j < t; j++) {
string temp;
cin >> temp;
a += temp;
}
Q[i].answer = a;
}
getchar(); // 前面是普通的cin,是不会读取掉行末的空字符的,后面getchar会先读取这个空字符,故要把空字符拿掉
for (int i = 0; i < n; i++) {
string ans; // 整行答案
string temp = ""; // 某个题目的学生答案
int t = 0; // 题目编号
getline(cin, ans); // 这句必须要引入string头文件才能用
for (int j = 0; j < ans.size(); j++) {
if (ans[j] >= 'a' && ans[j] <= 'z') { temp += ans[j]; }
if (ans[j] == ')') {
if (check(temp, t)) { student[i] += Q[t].score; }
else { Q[t].error++; }
t++;
temp = "";
}
}
}
for (int i = 0; i < n; i++) { cout << student[i] << endl; }
int m = 0; // 题目的最大出错次数
for (int i = 0; i < k; i++) {
if (Q[i].error > m) { m = Q[i].error; }
}
if (m != 0) {
cout << m;
for (int i = 0; i < k; i++) {
if (Q[i].error == m) { cout << " " << i + 1; }
}
}
else { cout << "Too simple"; }
return 0;
}