ccf真题 202012-2 期末预测之最佳阈值

在这里插入图片描述
这道题使用两层暴力循环会超时,第二次才拿满了分数
第一次的代码(70分):
思路非常简单,建立一个长度为n的结构体,每个结构体包含三个数值,y、result、以每个y为标准判断的正确次数right。
两个for循环嵌套求出每个y。
快排(优先级:right较大->y较大),输出第一个结构体的y值。
//由于使用了两层循环,会有部分样例超时。

#include<iostream>
#include<algorithm>
using namespace std;
struct classmate{
	int y;
	int result;
	int right;
	classmate():y(0),result(0),right(0){
	}
};
bool compare(const classmate& a,const classmate& b){
	if(a.right!=b.right)
	return a.right>b.right;
	else if(a.y!=b.y)
	return a.y>b.y;
	return 0;
}
int main(){
	int n;
	cin>>n;
	classmate student[n];
	for(int i=0;i<n;i++){
		cin>>student[i].y;
		cin>>student[i].result;
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(student[i].y>student[j].y&&student[j].result==0){
				student[i].right++;
			}
			else if(student[i].y<=student[j].y&&student[j].result==1){
				student[i].right++;
			}
		}
	}
	sort(student,student+n,compare);
	cout<<student[0].y<<endl;
}

第二次(100分):
思路也很简单,当我们将所有个体按照y从小到大的顺序排序时,每个结构体的right值都与前一个关系很大。
所以先将结构体数组按照y从小到大的顺序排序。
我们可以知道,每个结构体单元(除了第一个)与前一个结构体单元的关系只有两种:y相等,y大于。
1、当y相等时,这时由于y值一样,所以他们预测结果的正确数量也相同,直接将前一个的right赋给他即可。
2、当y大于时,如果前面的(假如y不是重复数)的right值为1,我们要减掉1才能将前一个right赋给他;同理,如果是0,则加1。
但是前面的数(y)可能是一堆重复数(比如:1 2 2 2 5,5前面就是一堆重复数),这个时候我们通过zero记录这些重复数中result为0的个数,one记录这些重复数中为1的个数。我们只需要仿照没有重复数的时候,前一个的right减去one加上zero即可。
每次当结构体单元的y值与前一个不同时,即对zero和one进行初始化。

#include<iostream>
#include<algorithm>
using namespace std;
struct classmate{
	int y;
	int result;
	int right;
	classmate():y(0),result(0),right(0){
	}
};
bool compare1(const classmate& a,const classmate& b){
	if(a.right!=b.right)
	return a.right>b.right;
	else if(a.y!=b.y)
	return a.y>b.y;
	return 0;
}
bool compare2(const classmate& a,const classmate& b){
	if(a.y!=b.y)
	return a.y<b.y;
	return 0;
}
int main(){
	int n;
	cin>>n;
	classmate student[n];
	for(int i=0;i<n;i++){
		cin>>student[i].y;
		cin>>student[i].result;
	}
	sort(student,student+n,compare2);
	//按照y值从小到大的顺序排序
	int zero=0,one=0;
	for(int i=0;i<n;i++){
		if(i==0){
			for(int j=0;j<n;j++){
				if(student[i].y>student[j].y&&student[j].result==0){
					student[i].right++;
				}
				else if(student[i].y<=student[j].y&&student[j].result==1){
					student[i].right++;
				}
			}
			if(student[i].result==0){
				zero=1;
			}
			else{
				one=1;
			}
		}
		//先把第一个单元的各种数值计算出来
		else if(student[i].y==student[i-1].y){
			student[i].right=student[i-1].right;
			if(student[i].result==0){
				zero++;
			}
			else{
				one++;
			}
		}
		//相等的情况,直接继承right值即可,然后对zero和one进行计数
		else{
			student[i].right=student[i-1].right-one+zero;
			if(student[i].result==0){
				zero=1;
				one=0;
			}
			else{
				zero=0;
				one=1;
			}
		}
		//不相等的情况,将上一个的right值减one加zero即可,别忘了对one和zero初始化
	}
	sort(student,student+n,compare1);
	//按照题目要求,以right值为第一优先级,从大到小排序
	//以y值为第二优先级,从大到小排序
	cout<<student[0].y<<endl;
	//输出第一个的y值即可
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值