题解 P3692 【夏幻的考试】

· · 题解

开始写题解就停不下来了orz

这是本蒟蒻的第十二篇题解,依旧是蒟蒻的布星的画风qwq.dalao可以自行跳过我啰啰嗦嗦的分析.

看到题面(标签)的第一眼,我就知道,这是一道模拟题,所以本题最最最基础的思路在于,将题目所有描述的操作直接模拟出来。

因为这道题目很明显可以看得出来是分为三个部分的模拟,分别是判断考号,判断卷子,以及最后的计算得分,所以我的想法是利用函数进行分块的处理,这样子代码可读性会更强,同时调试起来也会更加的方便。

Step1:模拟判断考号

因为所有考号读入时没有空格,同时考号的位数已知为16位,这里可以利用循环进行读入,在读入的同时在线进行考号2进制与10进制的转换,具体的转换式子是当第i位为1的时候id+=pow(2,16-i);

ps:这里需要注意的是不能使用整型读入,每次读入的是一个char字符。每一次在读入这个考号之前需要将id初始化为0!!!(我因为这个连样例都没有过orz)

核心转换代码实现:(c是一个字符)

    for(int i = 1;i<=16;i++){
        cin >> c;
        if(c-'0' == 1) id += pow(2,16-i);
    }

然后就判断一下id是不是在合法范围之内就ok了

Step2:模拟判断试卷

这一步的模拟就是比较轻松愉快了,根据上一步读入的最后一个字符判断是A卷还是B卷,用字符串读入然后直接把两种情况列出来判断就可以了。

核心判断代码实现:(qwq是指读入的填涂字符,g指考号最后一个字符)

    if((g == '1'&&qwq == "01")||(g == '0'&&qwq == "10")) printf("Type Correct\n");
    else printf("Type Incorrect\n");

Step3:模拟批改试卷

这个题目中最为复杂的就是最后一个模拟,有以下几个点值得思考:

下面一个一个来为大家讲解。

第一个是标准答案的存储。因为标准答案在进行读入时读入的是字符而不是填涂的01串,为了后面判断方便我在读入它们时就将它们转化为01串存入一个string中,就像这样:

    if(w[i] == 'A') s[i+1] = A;
    else if(w[i] == 'B') s[i+1] = B;
    else if(w[i] == 'C') s[i+1] = C;
    else s[i+1] = D;

当然ABCD四个是提前转化好的四个string

接下来是对读入的判断以及分数计算,同样是直接利用string读入,然后判断它和对应题目标准答案的字符串是否相等,如果不相等直接减去本题的分值,就像这样:

    for(int i = 1;i<=n;i++){
        cin >> qwq;
        if(qwq != s[i]) markk -= point;
    }

最后直接输出分值就可以了

以上就是对于本题算法思路的一个讲解。

BUT

本题最最最大的坑点不是算法,而是windows和linux的一些符号(比如换行符,scanf读入格式之类)的不兼容,我在本地成功的过了炒鸡多的样例,下载的数据也完美的通过,但是依旧不停的WA(爆0)

有记录截图为证: 最后我把所有的cout << endl全部都换成了\n,同时将所有的scanf全部都换成了cin,去掉了所有的gets,我终于成功了……

下面贴上代码,上面有代码讲解不够详细的请参考代码注释:

#include<bits/stdc++.h>
using namespace std;
int t,n;
char w[55];//标准答案字符存储
string s[55];//标准答案转换后字符串存储
string A = "1000";
string B = "0100";
string C = "0010";
string D = "0001";//四个提前转换好的填涂字符串
bool flg = true;//flg是一个标记,用来指明这个人是否需要继续处理下面的试卷
char c;
int id;
string qwq;
double markk,point;//分数,以及每一题的分值
void typ(){
    id = 0;//初始化id!这个超重要的
    for(int i = 1;i<=16;i++){
        cin >> c;
        if(c-'0' == 1) id += pow(2,16-i);
    }
    if(id >= 1&&id<=10000) printf("ID: %d\n",id);
    else {
        printf("Wrong ID\n");
        flg = false;//如果这个考号不合法,标记一下
    }
    return;
}
void check(char g){
    cin >> qwq;
    if(flg == false) return;
    else {
        if((g == '1'&&qwq == "01")||(g == '0'&&qwq == "10")) printf("Type Correct\n");
        else printf("Type Incorrect\n");
    }
    return;
}
void pas(){
    markk = 100.00;//初始化每一个人的分数
    for(int i = 1;i<=n;i++){
        cin >> qwq;
        if(qwq != s[i]) markk -= point;
    }
    if(flg == false)return;
    printf("%.1lf\n",markk);//输出格式要注意啊
}
int main(){
    std::ios::sync_with_stdio(false);//让cin和scanf一样快的神器~
    cin >> t >> n;
    cin >> w;
    for(int i = 0;i<n;i++){
        if(w[i] == 'A') s[i+1] = A;
        else if(w[i] == 'B') s[i+1] = B;
        else if(w[i] == 'C') s[i+1] = C;
        else s[i+1] = D;
    }
    point = 100.00/n;//求每题分值 
    for(int i = 1;i<=t;i++){
        flg = true;//初始化这张试卷的状态
        typ();//判断考号合法性
        check(c);//因为c是全局变量所以可以直接传
        pas();//考试成绩
        printf("\n");//千万不能忘了这里有一个换行!
    }
    return 0;
}

一道简单有趣的模拟题就这样完美AC了!当然这道题的模拟思路确实非常清晰明了是一道完美的练习题~

希望这篇题解对大家能有所帮助。

而且既然都看到这里了,点个赞再走行不(≖‿≖)✧