批改多选题是比较麻烦的事情,有很多不同的计分方法。有一种最常见的计分方法是:如果考生选择了部分正确选项,并且没有选择任何错误选项,则得到 50% 分数;如果考生选择了任何一个错误的选项,则不能得分。本题就请你写个程序帮助老师批改多选题,并且指出哪道题的哪个选项错的人最多。
输入格式:
输入在第一行给出两个正整数 N(≤1000)和 M(≤100),分别是学生人数和多选题的个数。随后 M 行,每行顺次给出一道题的满分值(不超过 5 的正整数)、选项个数(不少于 2 且不超过 5 的正整数)、正确选项个数(不超过选项个数的正整数)、所有正确选项。注意每题的选项从小写英文字母 a 开始顺次排列。各项间以 1 个空格分隔。最后 N 行,每行给出一个学生的答题情况,其每题答案格式为 (选中的选项个数 选项1 ……)
,按题目顺序给出。注意:题目保证学生的答题情况是合法的,即不存在选中的选项数超过实际选项数的情况。
输出格式:
按照输入的顺序给出每个学生的得分,每个分数占一行,输出小数点后 1 位。最后输出错得最多的题目选项的信息,格式为:错误次数 题目编号(题目按照输入的顺序从1开始编号)-选项号
。如果有并列,则每行一个选项,按题目编号递增顺序输出;再并列则按选项号递增顺序输出。行首尾不得有多余空格。如果所有题目都没有人错,则在最后一行输出 Too simple
。
输入样例 1:
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)
输出样例 1:
3.5
6.0
2.5
2 2-e
2 3-a
2 3-b
输入样例 2:
2 2
3 4 2 a c
2 5 1 b
(2 a c) (1 b)
(2 a c) (1 b)
输出样例 2:
5.0
5.0
Too simple
这个题写了好长时间,先是用java写的,写了之后最后一个测试点运行超时。试着改成set集合,想着能快点,但还是不行。最后同样的思路换成了C语言通过了。
import java.util.Arrays;
import java.util.Scanner; public class Hello {
static int N,M;//学生个数,选项数
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
M = sc.nextInt();
Q[] q = new Q[M];
Stu[] stu = new Stu[N];
String temp;//临时变量
char[] temp1;//临时变量
char[] temp2;//临时变量
for(int i=0;i<M;i++) {
q[i] = new Q();
q[i].a = sc.nextInt();
q[i].b = sc.nextInt();
q[i].c = sc.nextInt();
q[i].e = new int[q[i].b];//选项初始化
temp = sc.nextLine();
temp1 = temp.toCharArray();
int k = 0;
//将正确选项存入问题类中的d属性中。
for(int j=0;j<temp1.length;j++) {
if(temp1[j]!= ' ')
q[i].d[k++] = temp1[j];
}
}
//学生答案的输入。最终将学生答题情况存入学生类的a属性中。
for(int i=0;i<N;i++) {
temp = sc.nextLine();
stu[i] = new Stu();
temp1 = temp.toCharArray();
temp2 = new char[temp1.length];
int k = 0;
for(int j=0;j<temp1.length;j++) {
if(temp1[j]!=' '&&temp1[j]!='('&&temp1[j]!=')') {
temp2[k++] = temp1[j];
}
}
int k1 = -1;
int k2 = 0;
for(int j=0;j<k;j++) {
if(temp2[j]<='g'&&temp2[j]>='a') {
stu[i].a[k1].d[k2++] = temp2[j];
}else {
k1++;
stu[i].a[k1] = new Q();
stu[i].a[k1].c = temp2[j]-'0';
k2 = 0;
}
} }
for(int i=0;i<N;i++) {
for(int j=0;j<M;j++) {
//如果学生答案个数比正确答案少
if(stu[i].a[j].c<=q[j].c) {
int flag = 0;//是否全部答对
char[] temp3 = q[j].d.clone(); for(int k=0;k<stu[i].a[j].c;k++) {
int k1 = 0;
//检查学生某个答案是在正确答案中
for(k1=0;k1<q[j].c;k1++) {
//如果在则跳出,并标记此答案没有答错
if(q[j].d[k1]==stu[i].a[j].d[k]) {
temp3[k1] = 'q';
break; }
}
//如果不在,则说明学生此答案答错
if(k1==q[j].c) {
q[j].e[stu[i].a[j].d[k]-'a']++;
flag = 1;//不得分
} }
//部分正确答案学生没有答出标记此答案也错了
for(int k=0;k<q[j].c;k++) {
if(temp3[k]!='q') {
q[j].e[temp3[k]-'a']++;
}
}
//如果没有答错
if(flag==0) {
//如果学生选项个数跟正确答案个数相同则满分
if(stu[i].a[j].c==q[j].c)
stu[i].mark += q[j].a;
//如果知只是部分答对
else
stu[i].mark += (double)q[j].a/2;
}
}
//处理学生答案比正确答案长的情况,处理相同,只是不得分。
else {
char[] temp3 = q[j].d.clone();
for(int k=0;k<stu[i].a[j].c;k++) {
int k1 = 0;
for(k1=0;k1<q[j].c;k1++) {
if(q[j].d[k1]==stu[i].a[j].d[k]) {
temp3[k1] = 'q';
break; }
}
if(k1==q[j].c) {
q[j].e[stu[i].a[j].d[k]-'a']++;
} }
for(int k=0;k<q[j].c;k++) {
if(temp3[k]!='q') {
q[j].e[temp3[k]-'a']++;
}
}
}
}
}
//输出分数。
for(int i=0;i<N;i++) {
System.out.println(stu[i].mark);
}
int max = 0;
//统计答案错的最多的次数
for(int i=0;i<M;i++) {
for(int j=0;j<q[i].b;j++) {
if(q[i].e[j]>max)
max = q[i].e[j];
}
}
//没有答错
if(max==0) {
System.out.println("Too simple");
}else {
//找出错的最多的选项与答案并输出。
for(int i=0;i<M;i++) {
for(int j=0;j<q[i].b;j++) {
if(q[i].e[j]==max) {
System.out.println(max+" "+(i+1)+"-"+(char) (j+'a'));
} }
}
}
}
public static class Stu{
Q[] a = new Q[M];//学生答案
double mark = 0;//学生分数
} public static class Q{//问题类
int a;//满分
int b;//选项个数
int c;//正确选项数
char[] d = new char[5];//正确选项
int[] e;//选项错误次数
} }
JAVA版
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set; public class Test {
static int N,M;//学生个数,选项数
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
M = sc.nextInt();
Q[] q = new Q[M];
Stu[] stu = new Stu[N];
String temp;//临时变量
char[] temp1;//临时变量
char[] temp2;//临时变量
for(int i=0;i<M;i++) {
q[i] = new Q();
q[i].a = sc.nextInt();
q[i].b = sc.nextInt();
q[i].c = sc.nextInt();
q[i].e = new int[q[i].b];//选项初始化
temp = sc.nextLine();
temp1 = temp.toCharArray();
int k = 0;
//将正确选项存入问题类中的d属性中。
for(int j=0;j<temp1.length;j++) {
if(temp1[j]!= ' ')
q[i].d.add(temp1[j]);
}
}
//测试正确答案是否存入集合中
/*for(int i=0;i<M;i++) {
for(char a:q[i].d) {
System.out.print(a);
}
System.out.println();
}*/
//学生答案的输入。最终将学生答题情况存入学生类的a属性中。
for(int i=0;i<N;i++) {
temp = sc.nextLine();
stu[i] = new Stu();
stu[i].d = new HashSet[M];
temp1 = temp.toCharArray();
temp2 = new char[temp1.length];
int k = 0;
for(int j=0;j<temp1.length;j++) {
if(temp1[j]!=' '&&temp1[j]!='('&&temp1[j]!=')') {
temp2[k++] = temp1[j];
}
}
int k1 = -1;
int k2 = 0;
for(int j=0;j<k;j++) {
if(temp2[j]<='g'&&temp2[j]>='a') {
stu[i].d[k1].add(temp2[j]);
}else {
k1++;
stu[i].d[k1] = new HashSet<>();
k2 = 0;
}
} }
//测试学生答案是否录入
/*for(int i=0;i<N;i++) {
for(int j=0;j<M;j++) {
for(char a:stu[i].d[j]) {
System.out.print(a);
}
System.out.print(" ");
}
System.out.println();
}*/
for(int i=0;i<N;i++) {
Set<Character> temp3 = new HashSet();
Set<Character> temp4 = new HashSet();
for(int j=0;j<M;j++) {
temp3.addAll(q[j].d);
temp4.addAll(stu[i].d[j]);
for(char a:temp4) {
if(temp3.contains(a)) {
temp3.remove(a);
stu[i].d[j].remove(a);
}
}
for(char a:stu[i].d[j]) {
q[j].e[a-'a']++;
}
for(char a:temp3) {
q[j].e[a-'a']++;
}
if(stu[i].d[j].size()==0) {
if(temp3.size()==0)
stu[i].mark += q[j].a;
else
stu[i].mark += (double)q[j].a/2;
}
temp3.clear();
temp4.clear();
}
}
//输出分数。
for(int i=0;i<N;i++) {
System.out.println(stu[i].mark);
}
int max = 0;
//统计答案错的最多的次数
for(int i=0;i<M;i++) {
for(int j=0;j<q[i].b;j++) {
if(q[i].e[j]>max)
max = q[i].e[j];
}
}
//没有答错
if(max==0) {
System.out.println("Too simple");
}else {
//找出错的最多的选项与答案并输出。
for(int i=0;i<M;i++) {
for(int j=0;j<q[i].b;j++) {
if(q[i].e[j]==max) {
System.out.println(max+" "+(i+1)+"-"+(char) (j+'a'));
} }
}
} } public static class Stu{
Set<Character>[] d;//学生答案
double mark = 0;
}
public static class Q{
int a;//满分
int b;//选项个数
int c;//正确选项数
Set<Character> d = new HashSet();//正确答案
int[] e;//选项错误次数
}
}
JAVA版(Set)
#include<stdio.h> typedef struct Q1{//问题类
int a;//满分
int b;//选项个数
int c;//正确选项个数
char d[];//正确选项
int e[];//选项错误次数
}Q;
typedef struct Stu1{//学生类
double mark;//学生分数
Q q[];//学生答案 }Stu;
Q q[];
Stu stu[];
int main(){
int N,M;//学生个数,选项数
scanf("%d %d",&N,&M);
for(int i=;i<M;i++){//录入问题
scanf("%d %d %d",&q[i].a,&q[i].b,&q[i].c);
for(int j=;j<q[i].c;j++){
scanf(" %c",&q[i].d[j]);
}
}
getchar();//接收回车符
for(int i=;i<N;i++){//录入学生答题
for(int j=;j<M;j++){
//getchar();
scanf("(%d",&stu[i].q[j].c);
for(int k=;k<stu[i].q[j].c;k++){
scanf(" %c",&stu[i].q[j].d[k]);
}
getchar();//接收'('符
getchar();//接收空格符
}
}
for(int i=;i<N;i++){
for(int j=;j<M;j++){
//如果学生答案个数比正确答案少
if(stu[i].q[j].c<=q[j].c){
int flag = ;
int temp[] = {};
for(int k=;k<stu[i].q[j].c;k++){
int k1 = ;
//检查学生某个答案是否在正确答案中,可以用集合,比较方便
for(k1=;k1<q[j].c;k1++){
//如果在则跳出,并标记此答案没有答错
if(q[j].d[k1]==stu[i].q[j].d[k]){
temp[k1] = ;
break;
}
}
//如果不在,则说明学生此答案答错
if(k1==q[j].c){
q[j].e[stu[i].q[j].d[k]-'a']++;
flag = ;//不得分
} }
//部分正确答案学生没有答出标记此答案也错了
for(int k=;k<q[j].c;k++){
if(temp[k]!=){
q[j].e[q[j].d[k]-'a']++;
}
}
//如果没有答错
if(flag==){
if(stu[i].q[j].c==q[j].c)
//如果学生选项个数跟正确答案个数相同则满分
stu[i].mark += q[j].a;
else
//如果知只是部分答对
stu[i].mark += (double)q[j].a/; }
}
//处理学生答案比正确答案长的情况,处理相同,只是不得分。
else{
int temp[] = {};
for(int k=;k<stu[i].q[j].c;k++){
int k1 = ;
for(k1=;k1<q[j].c;k1++){
if(q[j].d[k1]==stu[i].q[j].d[k]){
temp[k1] = ;
break;
}
}
if(k1==q[j].c){
q[j].e[stu[i].q[j].d[k]-'a']++;
} }
for(int k=;k<q[j].c;k++){
if(temp[k]!=){
q[j].e[q[j].d[k]-'a']++;
}
}
} }
}
//输出分数。
for(int i=;i<N;i++){
printf("%0.1lf\n",stu[i].mark);
}
int max =;
//统计答案错的最多的次数
for(int i=;i<M;i++){
for(int j=;j<q[i].b;j++){
if(q[i].e[j]>max){
max = q[i].e[j];
}
}
}
//没有答错
if(max==){
printf("Too simple\n");
}else{
//找出错的最多的选项与答案并输出。
for(int i=;i<M;i++){
for(int j=;j<q[i].b;j++){
if(q[i].e[j]==max){
printf("%d %d-%c\n",max,i+,j+'a');
}
}
}
} }