/**
* 1.解题思路:错误是指错选或者漏选。用异或运算来判断一个选项和正确选项是否匹配
* 如果是匹配的,那么异或的结果应当是0;如果不匹配
* 那么这个选项就是存在错选或者漏选的情况
* 例如:设a为00001,b为00010,c为00100,d为01000,e为10000
* 如果给定的正确答案是ac,即10001,那么如果给出的选项也是10001
* 异或的结果就是0;如果给出的选项是a或者ab,即00001或00011,异或之后不为0
* 就是错选和漏选的~通过异或操作的结果,再用与运算就可以把错选和漏选的选项找出来
* fullscore表示一道题满分的分值;trueopt表示正确的选项,存储的是正确选项二进制的值
* 二进制由hash给出分别是1,2,4,8,16;cnt是错误的次数,maxcnt是最大错误次数
*
* 2.异或:如果a、b两个值不相同,则异或结果为1。 如果a、b两个值相同,异或结果为0
*
* 3.参考博客:https://pintia.cn/problem-sets/994805260223102976/problems/994805263624683520
**/
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main() {
//maxcnt是最大错误次数
int n, m, optnum, truenum, temp, maxcnt = 0;
//二进制由hash给出分别是1,2,4,8,16
int hash[] = {1, 2, 4, 8, 16}, opt[1010][110] = {0};
char c;
scanf("%d %d", &n, &m);
//fullscore表示一道题满分的分值;trueopt表示正确的选项,存储的是正确选项二进制的值
vector<int> fullscore(m), trueopt(m);
//cnt是错误的次数
vector<vector<int>> cnt(m, vector<int>(5));
//一道题的满分值 选项个数 正确选项个数
for (int i = 0; i < m; i++) {
scanf("%d %d %d", &fullscore[i], &optnum, &truenum);
for (int j = 0; j < truenum; j++) {
scanf(" %c", &c);
trueopt[i] += hash[c-'a'];
}
}
for (int i = 0; i < n; i++) {
double grade = 0;
for (int j = 0; j < m; j++) {
getchar();
scanf("(%d", &temp);
for (int k = 0; k < temp; k++) {
scanf(" %c)", &c);
opt[i][j] += hash[c-'a'];
}
//异或
int el = opt[i][j] ^ trueopt[j];
if (el) {
//部分选项
if ((opt[i][j] | trueopt[j]) == trueopt[j]) {
grade += fullscore[j] * 1.0 / 2;
}
if (el) {
for (int k = 0; k < 5; k++)
if (el & hash[k]) cnt[j][k]++;
}
} else {
grade += fullscore[j];
}
}
printf("%.1f\n", grade);
}
//找出最大错误次数
for (int i = 0; i < m; i++)
for (int j = 0; j < 5; j++)
maxcnt = maxcnt > cnt[i][j] ? maxcnt : cnt[i][j];
if (maxcnt == 0) {
printf("Too simple\n");
} else {
for (int i = 0; i < m; i++) {
for (int j = 0; j < cnt[i].size(); j++) {
if (maxcnt == cnt[i][j])
printf("%d %d-%c\n", maxcnt, i+1, 'a'+j);
}
}
}
return 0;
}
1073 多选题常见计分法
最新推荐文章于 2019-08-31 16:48:58 发布