PAT乙级1085(下)

一把辛酸泪地琢磨了好久怎么超时的......最后靠一半辛苦一半玄学终于通过了所有测试点。先上代码

#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<utility>
#include<cstring>
using namespace std;
class output{
	public:
		string school;
		double scoreb;
		double scorea;
		double scoret;
		int popu;
		int score;
		output(string s,double b,double a,double t,int po){
			school=s;scoreb=b;scorea=a;scoret=t;popu=po;score=0;
		}
		output(){
			school="";scoreb=0;scorea=0;scoret=0;popu=0;score=0;
		}
		void cal(){
			score=(scoreb/1.5)+scorea+scoret*1.5;
			return;
		}
		void p(){
			cout<<school;//
			printf(" %d %d\n",score,popu);
			return;
		}
};
bool cmp(output a,output b){
	if(a.score!=b.score){
		return a.score>b.score;
	}
	else if(a.popu!=b.popu){
		return a.popu<b.popu;
	}
	else{
		return a.school<b.school;
	}
}
int main(){
	int n;
	cin>>n;
	map<string,output> out;
	vector<output> outvec;
	for(int i=0;i<n;i++){
		char id[12],school[12];
		double score;
		scanf("%s %lf %s",id,&score,school);
		
		for(int i=0;i<strlen(school);i++){
			if(isupper(school[i])){
				school[i]=tolower(school[i]);
			}
		}
		double scoreb=0,scorea=0,scoret=0;
		if(id[0]=='T'){
			scoret=score;
		}
		else if(id[0]=='B'){
			scoreb=score;
		}
		else{
			scorea=score;
		}
		if(out[school].school==""){
			out[school].school=school;
		}
		
		(out[school].scoreb)+=scoreb;
		(out[school].scorea)+=scorea;
		(out[school].scoret)+=scoret;
		(out[school].popu)+=1;
	}
	cout<<out.size()<<endl;
	map<string,output>::iterator itermap=out.begin();
	while(itermap!=out.end()){
		(itermap->second).cal();
		outvec.push_back(itermap->second);
		itermap++;
	}
	sort(outvec.begin(),outvec.end(),cmp);
	
	int rank=1,rank2=1;
		for(int i=0;i<outvec.size();i++){
			if(i!=0&&outvec[i].score==outvec[i-1].score){
				printf("%d ",rank);
			}
			else{
				rank=rank2;
				printf("%d ",rank);
			}
			rank2++;
			outvec[i].p();
		}
	return 0;
} 

第一个超时的地方在于,刚开始使用冒泡排的序,问题是冒泡时间复杂度n^2,数据规模10^5,限时500ms(被csp惯坏了习惯了1s......)就肯定超时了啊。在我恍然大悟之后,改用sort排序,然而依然超时。然后经过仔细排查,多方实验,发现最大的问题可能是输入输出用了c++的流,以前就听说过会比scanf和printf慢好多,但是没因为这个超过时(没错我就是被csp惯的......)改了以后不超时了,换最后一个测试点报错了。

然后玄学的事情就出现了,本来刚开始我是怕超时仿照网上的代码把score分步计算最后再直接求和的(代码后面有),后来我怕double也会有碰巧误差一丢丢转成int就差1的情况,就又死马当活马医(因为网上的代码我试着提交是可以过的,所以没抱什么希望)地改回了先不计算score最后一起计算,结果居然过了所有测试点。我到现在也没有想明白这个问题......

但是提交的代码性能依然比网上的代码输了不少,但是过了就好过了就好......

在调试过程中总结了以下需要精进的知识,特此记录:

1.map使用key直接访问的时候会有如果key不存在自动insert一个新的映射的情况,所以如果map的second是自己构造的一个类,必须要写默认构造函数。

2.sort函数是可以自己规定比较大小的函数的,函数写在第三个形参。规则为,cmp(a,b),如果希望a排到前面就返回1,希望b排到前面就返回0。

3.printf输出double要用%lf,用c++用久了早就忘了......

4.string类型的不能用printf输出,如果非要用,用c_str()函数转换也可以。

差不多了~然后把那个带着玄学bug的(score计算方式更改之前的)粘过来,万一有好心人帮我看看呢?虽然我刚开博客不大可能哈哈~

#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<utility>
#include<cstring>
using namespace std;
class output{
	public:
		string school;
		int popu;
		double score;
		output(){
			school="";popu=0;score=0;
		}
		void p(){
			
			printf("%s %d %d\n",school.c_str(),(int)score,popu);
			return;
		}
};
bool cmp(output a,output b){
	if(a.score!=b.score){
		return a.score>b.score;
	}
	else if(a.popu!=b.popu){
		return a.popu<b.popu;
	}
	else{
		return a.school<b.school;
	}
}
int main(){
	int n;
	scanf("%d",&n);
	map<string,output> out;
	vector<output> outvec;
	for(int i=0;i<n;i++){
		char id[12],school[12];
		double score;
		scanf("%s %lf %s",id,&score,school);//
		
		for(int i=0;i<strlen(school);i++){
			if(isupper(school[i])){
				school[i]=tolower(school[i]);//
			}
		}
		double sumscore;
		if(id[0]=='T'){
			sumscore=score*1.5;
		}
		else if(id[0]=='B'){
			sumscore=score/1.5;
		}
		else{
			sumscore=score;
		}
		
		if(out[school].school==""){
			out[school].school=school;
		}
		//默认构造 
		(out[school].score)+=sumscore;
		(out[school].popu)+=1;
	}
	cout<<out.size()<<endl;
	map<string,output>::iterator itermap=out.begin();
	while(itermap!=out.end()){
		outvec.push_back(itermap->second);
		itermap++;
	}
	sort(outvec.begin(),outvec.end(),cmp);//
	
	int rank=1,rank2=1;
		for(int i=0;i<outvec.size();i++){
			if(!(i!=0&&((int)outvec[i].score)==((int)outvec[i-1].score))){
				rank=rank2;
			}
			printf("%d ",rank);
			rank2++;
			outvec[i].p();
		}
	return 0;
} 

对啦,最后贴出一直指导我改bug的传说中的网上正确的代码链接点击打开链接

就这样啦,要加油刷题呀!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值