混沌者 pat basic 练习七十三 多选题常见计分法

心得:

1.当题目需要输出三项关联数据的时候,考虑用二维数据,第一项是一维做一个键,第二项是二维做另一个键,第三项是结果作为值

因为一般题目要输出两项,就是最简单的键值对;当三项的时候就考虑二维数组

2.这个题和第五十八一个系列,这题更难。本来五十八题我使用的字符串匹配在这里很麻烦

第一版代码很冗杂,复用性很差。  我看了别人的思路,就觉得很好,因为选项最多5项,所以

没必要用字符串匹配,直接声明一个长度5的数组,下标代表字母,如0代表a,4代表e,出现的选项就在对应下标赋值为1,这样1代表选的,0代表没选的,由此使用对应下标做减法运算即可判断对错

 

 

题目:

批改多选题是比较麻烦的事情,有很多不同的计分方法。有一种最常见的计分方法是:如果考生选择了部分正确选项,并且没有选择任何错误选项,则得到 50% 分数;如果考生选择了任何一个错误的选项,则不能得分。本题就请你写个程序帮助老师批改多选题,并且指出哪道题的哪个选项错的人最多。

输入格式:

输入在第一行给出两个正整数 N(≤1000)和 M(≤100),分别是学生人数和多选题的个数。随后 M 行,每行顺次给出一道题的满分值(不超过 5 的正整数)、选项个数(不少于 2 且不超过 5 的正整数)、正确选项个数(不超过选项个数的正整数)、所有正确选项。注意每题的选项从小写英文字母 a 开始顺次排列。各项间以 1 个空格分隔。最后 N 行,每行给出一个学生的答题情况,其每题答案格式为 (选中的选项个数 选项1 ……),按题目顺序给出。注意:题目保证学生的答题情况是合法的,即不存在选中的选项数超过实际选项数的情况。

输出格式:

按照输入的顺序给出每个学生的得分,每个分数占一行,输出小数点后 1 位。最后输出错得最多的题目选项的信息,格式为:错误次数 题目编号(题目按照输入的顺序从1开始编号)-选项号。如果有并列,则每行一个选项,按题目编号递增顺序输出;再并列则按选项号递增顺序输出。行首尾不得有多余空格。如果所有题目都没有人错,则在最后一行输出 Too simple

 

 

 

 

思路:

这个题个人觉得说明不明确,题目说要求记录错误的选项,这个"错误的选项"意思不止是选错的选项(即多选了一个错误的选项),还有漏选的选项(即少选了一个正确的选项),需要注意

第一版我使用了字符串匹配,很麻烦,基本很难看懂

 

在看了别人思想更进了代码之后,就很明确了

就是声明一个长度5的选项数组,下标代表字母,如0代表a,4代表e,出现的选项就在对应下标赋值为1,这样1代表选的,0代表没选的,然后将正确答案和学生选的答案进行比较(这里我直接做减法来判断),就可以判断是否做错或者做全对或者做部分对

 

第一版代码:

#include<iostream>
#include<map>
#include<vector>
#include<cstdio>
using namespace std;
struct ques
{
    int score;
    int opt_num;
    int right_num;
    string ans;
};
int main()
{
    int stu_num,ques_num,max_num=0;
    vector<ques> q;
    cin>>stu_num>>ques_num;
    int right_opt[ques_num][5]={};
    int wrong_opt_num[ques_num][5]={};
    for(int i=0;i<ques_num;i++)
    {
        ques temp;
        string t_str="";
        char t_ch;
        cin>>temp.score>>temp.opt_num>>temp.right_num;
        for(int j=0;j<temp.right_num;j++)
        {
            cin>>t_ch;
            right_opt[i][t_ch-'a']=1;
            t_str+=t_ch;
        }
        temp.ans=t_str;
        q.push_back(temp);
    }
    for(int i=0;i<stu_num;i++)
    {
        double this_stu_score=0.0;
        for(int j=0;j<ques_num;j++)
        {
            cin.ignore();
            bool is_wrong=false;
            int this_opt_num;
            string this_ans="";
            char t_ch,t_c;
            scanf("(%d",&this_opt_num);
            for(int k=0;k<this_opt_num;k++)
            {
                cin>>t_ch;
                this_ans+=t_ch;
            }
            scanf(")");
            if(this_ans.size()==q.at(j).ans.size())
            {
                for(int k=0;k<q.at(j).ans.size();k++)
                {
                    int t=this_ans.find(q.at(j).ans.at(k));
                    if(t==this_ans.npos)
                        wrong_opt_num[j][q.at(j).ans.at(k)-'a']++;
                    if(wrong_opt_num[j][q.at(j).ans.at(k)-'a']>max_num)
                            max_num=wrong_opt_num[j][q.at(j).ans.at(k)-'a'];
                }
                for(int k=0;k<q.at(j).ans.size();k++)
                {
                    if(right_opt[j][this_ans.at(k)-'a']!=1)
                    {
                        is_wrong=true;
                        wrong_opt_num[j][this_ans.at(k)-'a']++;
                        if(wrong_opt_num[j][this_ans.at(k)-'a']>max_num)
                            max_num=wrong_opt_num[j][this_ans.at(k)-'a'];
                    }
                }
                if(!is_wrong)
                    this_stu_score+=q.at(j).score;
            }
            else
            {
                for(int k=0;k<q.at(j).ans.size();k++)
                {
                    int t=this_ans.find(q.at(j).ans.at(k));
                    if(t==this_ans.npos)
                        wrong_opt_num[j][q.at(j).ans.at(k)-'a']++;
                    if(wrong_opt_num[j][q.at(j).ans.at(k)-'a']>max_num)
                            max_num=wrong_opt_num[j][q.at(j).ans.at(k)-'a'];
                }
                for(int k=0;k<this_ans.size();k++)
                {
                    if(right_opt[j][this_ans.at(k)-'a']!=1)
                    {
                        is_wrong=true;
                        wrong_opt_num[j][this_ans.at(k)-'a']++;
                        if(wrong_opt_num[j][this_ans.at(k)-'a']>max_num)
                            max_num=wrong_opt_num[j][this_ans.at(k)-'a'];
                    }
                }
                if(!is_wrong)
                    this_stu_score+=q.at(j).score*1.0/2;
            }
        }
        printf("%.1f\n",this_stu_score);
    }
    if(max_num==0)
        printf("Too simple\n");
    else
    {
        for(int i=0;i<ques_num;i++)
        {
            for(int j=0;j<5;j++)
            {
                if(wrong_opt_num[i][j]==max_num)
                    printf("%d %d-%c\n",max_num,i+1,j+'a');
            }
        }
    }
    return 0;
}

 

第二版代码: 

#include<iostream>
#include<map>
#include<vector>
#include<cstdio>
using namespace std;
struct ques
{
    int score;
    int opt_num;
    int right_num;
    int right_opt[5]={};//这个数组是每个题的正确答案
};
int main()
{
    int stu_num,ques_num,max_num=0;
    cin>>stu_num>>ques_num;
    int wrong_opt_num[ques_num][5]={};//这个二维数组就是记录某个题的某个选项的错误次数
    vector<ques> q;
    for(int i=0;i<ques_num;i++)
    {
        ques temp;
        char t_ch;
        cin>>temp.score>>temp.opt_num>>temp.right_num;
        for(int j=0;j<temp.right_num;j++)
        {
            cin>>t_ch;
            temp.right_opt[t_ch-'a']=1;//对应的下标赋值为1
        }
        q.push_back(temp);
    }
    for(int i=0;i<stu_num;i++)
    {
        double this_stu_score=0.0;
        for(int j=0;j<ques_num;j++)
        {
            int stu_opt_num;
            char t_ch;
            bool is_wrong=false,is_part=false;
            int opt[5]={};//这个数组存学生选择的选项
            cin.ignore();
            scanf("(%d",&stu_opt_num);
            for(int k=0;k<stu_opt_num;k++)
            {
                cin>>t_ch;
                opt[t_ch-'a']=1;//也是对应下标赋值为1
            }
            cin.ignore();
            for(int k=0;k<5;k++)
            {//这个循环开始对每个选项判断

                int num=opt[k]-q.at(j).right_opt[k];//学生的选择和答案做减法
                if(num==1||num==-1)
                {//如果num=1说明多选了,即选了一个错误选项
                 //如果num=-1说明少选了,即没选某个正确选项
                 //这两种情况都是题目所说的"错误的选项"
                    wrong_opt_num[j][k]++;
                    if(wrong_opt_num[j][k]>max_num)
                        max_num=wrong_opt_num[j][k];
                    if(num==1)
                        is_wrong=true;
                    if(num==-1)
                        is_part=true;
                }
            }
            if(!is_wrong&&!is_part)//如果没多选也没少选,就给满分
                this_stu_score+=q.at(j).score;
            else if(!is_wrong&&is_part)//如果没多选但少选了,就给一般分
                this_stu_score+=q.at(j).score*1.0/2;
        }
        printf("%.1f\n",this_stu_score);
    }
    if(max_num==0)
        printf("Too simple\n");
    else
    {
        for(int i=0;i<ques_num;i++)
        {
            for(int j=0;j<5;j++)
            {
                if(wrong_opt_num[i][j]==max_num)
                    printf("%d %d-%c\n",max_num,i+1,j+'a');
            }
        }
    }
    return 0;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值