1073 多选题常见计分法 (20分)
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)
3.5
6.0
2.5
2 2-e
2 3-a
2 3-b
2 2
3 4 2 a c
2 5 1 b
(2 a c) (1 b)
(2 a c) (1 b)
5.0
5.0
Too simple
题意太坑了,输出错得最多的题目选项的信息,这个错的最多不是某个题的学生错误数最大,而是学生的选项错误数最大。
例如某个题答案bc,甲学生选择abc,乙学生选择bc,丙学生选择b,丁学生选择了abc。那么对于该题,题中所指的错误数不是3(甲丙丁做错了),而是2,甲丙丁三个人的选项放在一起,他们共计错选了2次a、漏选了1次c,2就是该题最大选项错误数。
漏选和错选都算错误,每个题的都有自己的最大错误数,它们之中的最大值就是需要输出的错误次数,测试点3和4就是这个问题。
最坑的是,它给的样例还完美符合把最大错误数当成每道题错误数的最大,我(lll¬ω¬)
在下就是一开始理解错了题意,参考网上代码才明白,以下代码是我在错误题意上改的,完全没必要和在下写的一样那么乱、那么冗杂,凑活当当参考吧,尽量注释清楚。实在不想重做了,心力憔悴啊/(ㄒoㄒ)/~~
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string>
using namespace std;
struct problem {//每道题的信息
double score;//分数
int sumchoice;//一共几个选项
int rightchoice;//正确选项的数量
string right;//正确选项的字符串,去除了空格,如:abc
};
struct wrong {//每道题的错误信息
int id;//该题的题号
int sum = 0;//学生做错了几次,理解错题意,现在可以删了
int choice[5] = {0};//每道选项做错了几次,下标0~5对应abcde
};
int cmp(struct wrong a, struct wrong b) {//理解错题意用的排序,可以删了
return (a.sum != b.sum) ? a.sum > b.sum : a.id < b.id;
}
int main() {
int n, m;
cin >> n >> m;
problem prs[m];//每道题
wrong ps[m];//每道题错误信息
int flag = 0;//记录最大的选项错误次数
for(int i = 1; i <= m; i++) {
cin >> prs[i - 1].score;
cin >> prs[i - 1].sumchoice;
cin >> prs[i - 1].rightchoice;
ps[i - 1].id = i;
for(int a = 1; a <= prs[i - 1].rightchoice; a++) {
char ch;
cin >> ch;//这样输入,空格就省略了
prs[i - 1].right += ch;
}
}
double everyscore[n] = {0};//每个学生的分数
for(int i = 1; i <= n; i++) {
for(int a = 1; a <= m; a++) {
char ch;
cin >> ch;//吸收左括号
int sum;
cin >> sum;
string answer;//学生答出的正确的选项
int re = 1; //表示本题的结果,-1一半分,1满分
int rights = 0; //学生答出的正确答案个数
for(int b = 1; b <= sum; b++) {//输入一个选项,判断一次
cin >> ch;
int index = prs[a - 1].right.find(ch);
if(index == -1) {//判断错选的
re = -1;//错选一个本题就0分
ps[a - 1].choice[ch - 'a']++;
if(ps[a - 1].choice[ch - 'a'] > flag)
flag = ps[a - 1].choice[ch - 'a'];
} else {
rights++;
answer += ch;
}
}
int thelen = prs[a - 1].right.size();
int re2 = 1;
for(int c = 1; c <= thelen; c++) {//判断漏选的,漏选选项,该选项也算做错
int index = answer.find(prs[a - 1].right[c - 1]);
if(index == -1) {
ps[a - 1].choice[prs[a - 1].right[c - 1] - 'a']++;
re2 = -1;
if(ps[a - 1].choice[prs[a - 1].right[c - 1] - 'a'] > flag)
flag = ps[a - 1].choice[prs[a - 1].right[c - 1] - 'a'];
}
}
cin >> ch;//吸收右括号
if(re == 1 && rights == thelen) {//满分
everyscore[i - 1] += prs[a - 1].score;
} else if(re != -1) {//一半分
everyscore[i - 1] += prs[a - 1].score * 0.5;
} else if(re == -1 || re2 == -1) {
ps[a - 1].sum++;//没什么用了,可以删了
}
}
}
for(int i = 1; i <= n; i++) {
printf("%.1lf\n", everyscore[i - 1]);
}
sort(ps, ps + m, cmp);//理解错题意的排序,无用了,可以删了
int index = 0;
if(flag == 0) {
cout << "Too simple" << endl;
} else {
while(index!=m) {
for(int i = 1; i <= 5; i++) {
if(ps[index].choice[i - 1] == flag) {
cout << flag << " " << ps[index].id << "-" << (char)('a' + (i - 1)) << endl;
}
}
index++;
}
}
return 0;
}
理解错题意,半小时打出代码,然后测试点3/4抠了1小时,发现题意理解错了。给的测试样例也真极品(ˉ▽ˉ;)…,完美符合错误的理解方式。还是在下辣鸡啊,慢慢学吧ε=( o`ω′)ノ