PAT (Basic Level) 1073 多选题常见计分法(恶心模拟)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_45458915/article/details/102753750

题目链接:点击查看

题目大意:1058的升级版,批改多选题,全对得满分,半对的半分,有错误选项不得分,最后统计出每个学生的成绩,以及哪个题目的哪个选项错误的次数最多,若有并列,依次输出

题目分析:目前为止pat里最恶心的模拟题,没有之一,并且这个题目不知道是不是有一个很奇怪的测试点把我卡了,网上去找题解也没找到关于那个测试点的描述,在努力了一个下午加一个晚上之后选择放弃(nmd,为了追求完美浪费了那么多时间,这什么破题?)因为熟练的运用stl,所以这个题目的实现并不是那么麻烦,但就是得不了满分,不知道为什么

需要注意的就是,错误选项有两个概念:

  1. 学生选上的选项里的错误选项
  2. 学生未选上的正确选项

我们都需要统计次数

直接挂代码吧,懒得做了,18分的菜鸡代码:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
#include<unordered_map>
using namespace std;
 
typedef long long LL;
 
const int inf=0x3f3f3f3f;
 
const int N=110;

int mark[N];//分数 格式:mark[题号]=分数 
 
unordered_map<string,bool>mp[N];//正确答案 格式:mp[题号][答案]=是否存在 

unordered_map<char,bool>mmp[N];//正确答案 格式:mmp[题号][每一个正确选项]=是否存在 

int cnt[N][150]={0};//错题选项 格式:cnt[题号][选项]=个数 (选项我是用ASCII码来储存的) 
 
double ans[N*10]={0};//分数 格式:ans[学生序号]=分数
 
int main()
{
//  freopen("input.txt","r",stdin);
	int n,m;
	scanf("%d%d",&n,&m);
   	for(int i=1;i<=m;i++)
   	{
   		int num;
   		scanf("%d%*d%d",mark+i,&num);
   		char ch[5];
   		string s;
   		for(int j=0;j<num;j++)
   		{
   			scanf("%s",ch);
   			s+=ch[0];
   			mmp[i][ch[0]]=true; 
		}
		mp[i][s]=true;
	}
	getchar();//注意!!!在cin或scanf与getline或gets连用时,已经记住要用getchar吃掉回车
   	for(int i=1;i<=n;i++)
   	{
   		string s;
   		getline(cin,s);//直接读一行,即当前学生的所有答案
   		for(int i=0;i<s.size();i++)//去掉所有的括号
   			if(s[i]=='('||s[i]==')')
   				s.erase(s.begin()+i);
   		stringstream ss(s);
   		int num;
   		char ch[5];
   		int pos=1;//题号 
   		while(ss>>num)
   		{
   			unordered_map<char,bool>mpmp;//记录学生选了哪些选项
			mpmp.clear(); 
   			string res;
   			bool flag=true;//是否有错误选项存在 
   			while(num--)
   			{
   				ss>>ch;
   				res+=ch[0];
   				mpmp[ch[0]]=true;
   				if(!mmp[pos][ch[0]])//如果有错误选项 
   				{
   					flag=false;
   					cnt[pos][ch[0]]++;//记录选错的编号 
				}
			}
			if(!flag)//有错误选项,记录一下有哪些正确选项没有选上 
			{
				string temp;//本个题目的正确答案 
				for(auto it=mp[pos].begin();it!=mp[pos].end();it++)
					temp=it->first;
				for(int j=0;j<temp.size();j++)//遍历一遍正确答案,看一看该学生少了哪些答案 
				{
					if(!mpmp[temp[j]])
						cnt[pos][temp[j]]++;//记录错误选项的次数 
				}
			}
			else//没有错误选项 
			{
				if(mp[pos][res])//全对得全分 
					ans[i]+=mark[pos];
				else//半对的一半分
				{
					ans[i]+=double(mark[pos])*0.5;
					string temp;//本个题目的正确答案 
					for(auto it=mp[pos].begin();it!=mp[pos].end();it++)
						temp=it->first;
					for(int j=0;j<temp.size();j++)//遍历一遍正确答案,看一看该学生少了哪些答案 
					{
						if(!mpmp[temp[j]])
							cnt[pos][temp[j]]++;//记录错误选项的次数 
					}
				} 
			}	
			pos++;
		}
	}
	for(int i=1;i<=n;i++)
		printf("%.1f\n",ans[i]);
	int mmax=0;//记录最多的错误选项个数 
	for(int i=1;i<=m;i++)
   		for(int j='a';j<='e';j++)
   			mmax=max(mmax,cnt[i][j]);
   	if(mmax==0)//没有错题 
   		cout<<"Too simple"<<endl;
   	else
   	{
   		for(int i=1;i<=m;i++)//遍历所有的题目
		{
			for(int j='a';j<='e';j++)
			{
				if(cnt[i][j]==mmax)
					printf("%d %d-%c\n",mmax,i,j);
			}
		} 
	}
   	
   	
   	
   	
   	
   	
     
     
     
     
     
     
     
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/102753750