【题解】CCF CSP 202012-2 —— 期末预测之最佳阈值

在这里插入图片描述

**解题心得:

题主在第一次做这题时,想尝试着用最简单的暴力算法去求解每个学生对应的 y 作为阈值时的正确率,但时间复杂度过大,无法应付最后30%的测试用例!

故之后采用优化后的算法,先将输入的每个学生的 y 值与是否挂科结果 result 存于已定义好的结构体中,然后将其结构体数组按每个元素的 y 值大小进行从大到小排序,这样可以得到一个以 y 值降序排列的结构体数组(方便于之后求解每个 y 作为阈值的正确率)!

**如何算每个 y 作为阈值的正确率 ?

首先,用最原始的办法遍历算出排在结构体数组中第一个,即 y 值最大的那个元素对应的正确率,通过与每个结构体元素的 y 进行比较。之后除第一个以外的所有结构体元素都无需再通过与所有结构体元素比较结果得到正确率,因为之后的所有元素对应的 y 值都小于等于第一个元素的 y 值,因此只需判断之后元素的 result 值是否为 1 或 0 :
若为 1 ,则说明对于上一个元素 y 值作为阈值时,此处判断失误(因为所有小于阈值的 y,都应该挂科 ),所以需将上一个元素的 y 值作为阈值的准确率个数 + 1 赋给当前元素的 y 值作为阈值时的准确率;
相反,若为 0 ,则说明当前元素 y 值作为阈值时,此处判断失误,而上一元素 y 值作为阈值时判断正确,因此当前元素 y 值作为阈值时,其正确率应当等于上一元素 y 值作为阈值时的正确率个数 – 1。
最后,通过一个一重for()循环即可算出所有结构体数组元素中 y 值作为阈值时的正确率个数,得出正确率最高的那个 y 值作为阈值θ。

**接下来上代码!!!

通过70%测试用例代码:

#include <iostream>
using namespace std;


int main()
{
	int m;
	cin >> m;
	long long  *y = new long long[m];
	int *result = new int[m];
	for(int i = 0; i < m; i++)
		cin >> y[i] >> result[i];
	
	int *count = new int[m];
	long long out;
	int out_count;
	
	for(int i = 0; i < m; i++)
	{
		count[i] = 0;
		for(int j = 0; j < m ; j++)
			if((y[j] >= y[i]) && (result[j] == 1)) count[i]++;
			else if ((y[j] < y[i]) && (result[j] == 0)) count[i]++;
		
		if(i == 0) 
		{
			out = y[0];
			out_count = count[0];
		}
		else if(count[i] > out_count) 
		{
			out = y[i];
			out_count = count[i];
		}
		else if(count[i] == out_count && y[i] > out) 
		{
			out = y[i]; 
			out_count = count[i];
		}	 
	}
	
	cout << out;
	return 0;
} 

在这里插入图片描述
通过100%测试用例代码:

#include <bits/stdc++.h>

using namespace std;

typedef struct {
	int y;		//安全指数
	int result;	//是否挂科
} Student;

bool Compare(Student stu1, Student stu2)
{
	return  stu1.y > stu2.y;	//按结构体中 y 从大到小进行排序
}

int main()
{
	int m;
	cin >> m;
	Student *stu = new Student[m];
	for(int i = 0; i < m; i++)
		cin >> stu[i].y >> stu[i].result;	//完成对m个学生是否挂科情况的初始化

	sort(stu, stu + m, Compare);
	
	int *count = new int[m];	//统计每个学生 y 作为阀值时的正确个数
	int out_count = 0;
	int out;
	
	for(int i = 0; i < m; i++)
	{
		count[i] = 0;			
		if(i == 0) {
			for(int j = 0; j < m ; j++)
				if((stu[j].y >= stu[i].y) && (stu[j].result == 1)) count[i]++;
				else if((stu[j].y < stu[i].y) && (stu[j].result == 0)) count[i]++;
		}	//仅仅对排在第一个,即 y 最大的元素进行一次全统计,算出count[0]的值
		else {
			if(stu[i].result == 0) count[i] = count[i-1] - 1;
			else count[i] = count[i-1] + 1;
		}

		if(stu[i].y != stu[i-1].y && i != 0 && count[i-1] > out_count) {
			out_count = count[i-1];
			out = stu[i-1].y;
		}
		
		if(i == m - 1 && count[i] > out_count) {
			out_count = count[i];
			out = stu[i].y;
		}
	}
	cout << out;
	return 0;
} 

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峰峰打怪兽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值