思路解析:本题可以通过结构体建立实际问题模型求解,也可以利用面向过程的思想,结合二进制的知识省去很多不必要的操作。第一种方法实现起来并不难,但会显得代码冗余,在这里对第二种进行讲解。
本算法核心思想是二进制的与或运算。
1⊕1=0、1⊕0=1、0⊕1=1、0⊕0=0
下面进行分析:
分别用00001、00010、00100、01000、10000 表示A、B、C、D、E五个选项,注意在存储时是存储的对应的十进制形式,也就是1、2、4、8、16
将每道题的正确答案用二进制表示并存储起来。
如答案为ABE则对应的二进制信息是00001 + 00010 + 10000 = 10011,注意,二进制运算是在计算机内部实现的,实际操作的数仍然是十进制,比如我们对00001和00010进行与运算,实际输入的数据是“1 & 2”,计算机会自动转成二进制,而不是我们手动输入二进制数的。
批卷过程是这样的:
首先将学生该题的全部选项与正确选项进行与或运算,若结果为0则说明答案正确,否则说明有错,哪一位为1说明那个选项出错,注意:错选与空选均算出错。
比如学生答案是10001,正确答案是10101,与或结果为00100,对应的十进制是4不是0,说明有错,而其对应的选项是C,说明该学生的C项出错。
示例代码:
#include<iostream>
#include<vector>
#include<iomanip>
using namespace std;
int main(){
int n,m; cin >> n>> m;
int hash[] = {1,2,4,8,16};//00001 00010 00100 01000 10000
vector<int> trueopt(m);//m道选择题的正确答案二进制信息对应的十进制数
int* fullscore = new int[m];//m道选择题的满分值
for(int i = 0; i < m; i++){//读题
int score, optnum, trunum;
scanf("%d %d %d",&score,&optnum,&trunum);
fullscore[i] = score;
for(int j = 0; j < trunum; j++){//读选项
char temp;
scanf(" %c",&temp);
trueopt[i] += hash[temp-'a'];//将所选答案信息全部读入到opt
}
}
vector<vector<int>> cnt(m,vector<int> (5));//二维数组 存储每道题每个选项的错误次数
for(int i = 0; i < n; i++){//执行n次 扫描每个学生
double grade = 0;
vector<int> stuopt(m);//创建临时数组 存储学生的答题情况
for(int j = 0; j < m; j++){//执行m次 扫描每道题
getchar();
int num; //学生选中的项数
scanf("(%d",&num);
for(int k = 0; k < num; k++){
char temp;
scanf(" %c)",&temp);//捎带着吃掉末尾的)
stuopt[j] += hash[temp-'a'];
}
}
for(int k = 0; k < m; k++){//执行m次 扫描学生选中的每道题
int el = stuopt[k] ^ trueopt[k];//进行与或运算
if(el){//大于0 说明有错误
if((el | trueopt[k]) == trueopt[k]){//将漏选的补上
grade += (double)fullscore[k]/2;
}
if(el){//统计错误信息
for(int j = 0; j <5; j++){//执行5次 选中5个选项
//el存储的是有歧义的选项 所以这些选项就是所求答案
if(el & hash[j]){
cnt[k][j]++;
}
}
}
}else{
grade += fullscore[k]*1.0;
}
}
cout<<setprecision(1)<<fixed<<grade<<endl;
}
int max = 0; //选出错的最多的那个选项
for(int i = 0; i < m; i++){
for(int j = 0; j < 5; j++){
max = cnt[i][j] > max ? cnt[i][j] : max;
}
}
if(!max){ //输出这些选项
cout<<"Too simple"<<endl;
}else{
for(int i = 0; i < m; i++){
for(int j = 0; j < 5; j++){
if(cnt[i][j] == max){
cout<<max<<" "<<i+1<<"-"<<char(j+'a')<<endl;
}
}
}
}
return 0;
}