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

题目背景

考虑到安全指数是一个较大范围内的整数、小菜很可能搞不清楚自己是否真的安全,顿顿决定设置一个阈值 ,以便将安全指数 转化为一个具体的预测结果——“会挂科”或“不会挂科”。

因为安全指数越高表明小菜同学挂科的可能性越低,所以当 时,顿顿会预测小菜这学期很安全、不会挂科;反之若 ,顿顿就会劝诫小菜:“你期末要挂科了,勿谓言之不预也。”

那么这个阈值该如何设定呢?顿顿准备从过往中寻找答案。

题目描述

具体来说,顿顿评估了 位同学上学期的安全指数,其中第 ()位同学的安全指数为
,是一个
范围内的整数;同时,该同学上学期的挂科情况记作
,其中 表示挂科、 表示未挂科。

相应地,顿顿用 表示根据阈值 将安全指数 转化为的具体预测结果。
如果

相同,则说明阈值为 时顿顿对第 位同学是否挂科预测正确;不同则说明预测错误。

最后,顿顿设计了如下公式来计算最佳阈值

该公式亦可等价地表述为如下规则:

最佳阈值仅在
中选取,即与某位同学的安全指数相同;

按照该阈值对这 位同学上学期的挂科情况进行预测,预测正确的次数最多(即准确率最高);

多个阈值均可以达到最高准确率时,选取其中最大的。

输入格式

从标准输入读入数据。

输入的第一行包含一个正整数 。

接下来输入 行,其中第 ()行包括用空格分隔的两个整数

,含义如上文所述。

输出格式

输出到标准输出。

输出一个整数,表示最佳阈值

样例1输入

6
0 0
1 0
1 1
3 1
5 1
7 1
Data

样例1输出

3
Data

样例1解释

按照规则一,最佳阈值的选取范围为 。

时,预测正确次数为 ;

时,预测正确次数为 ;

时,预测正确次数为 ;

时,预测正确次数为 ;

时,预测正确次数为 。

阈值选取为 或 时,预测准确率最高;
所以按照规则二,最佳阈值的选取范围缩小为 。

依规则三,

样例2输入

8
5 1
5 0
5 0
2 1
3 0
4 0
100000000 1
1 0
Data

样例2输出

100000000
Data
子任务
的测试数据保证 ;

全部的测试数据保证 。

源码

70分代码

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#pragma warning(disable:4996)
using namespace std;
//首先看到n为1e5,两层循环肯定是超时的,只能得70分!
const int N = 100000;
int main()
{
	int m;
	scanf("%d", &m);
	int arr[N][2];
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < 2; j++) {
			scanf("%d", &arr[i][j]);
		}
	}
	int NUM = 0, ret = 0;
	for (int i = 0; i < m; i++) {
		int flag = arr[i][0];
		int num = 0;
		for (int x = 0; x < m; x++) {
			if (arr[x][0] >= flag) {
				if (arr[x][1] == 1)num++;
			}
			else {
				if (arr[x][1] == 0)num++;
			}
		}
		if (num > NUM) {
			NUM = num;
			ret = flag;
		}
		else if (num == NUM) {
			if (flag > ret) {
				NUM = num;
				ret = flag;
			}
		}
	}
	printf("%d", ret);

	return 0;
}

100分代码

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include <algorithm>
#pragma warning(disable:4996)
using namespace std;
//满分代码
struct stu {//学生结构体
	int y;//安全指数
	int res;//是否挂科
};
bool cmp(stu s1, stu s2)
{
	return s1.y < s2.y;//从小到大排序
}
int main()
{
	int m;
	scanf("%d", &m);
	stu s[100000];
	for (int i = 0; i < m; i++) {
		scanf("%d %d", &s[i].y,&s[i].res);
	}
	//排序
	sort(s, s + m, cmp);//从小到大排序
	//先求第一个正确个数
	int num = 0;
	for (int i = 0; i < m; i++) {
		if (s[i].res == 1)num++;
	}
	int ret = s[0].y;

	int flag = num;
	//利用第一个求剩下所有的正确个数
	int equal_num = 0;
	int equal_num0 = 0;
	int equal_num1 = 0;
	for (int i = 1; i < m; i++) {
		if (s[i].y == s[i - 1].y) {
			equal_num++;
			if (s[i - 1].res == 0)equal_num0++;
			if (s[i - 1].res == 1)equal_num1++;
		}
		if (s[i].y != s[i - 1].y) {
			if (equal_num == 0) {
				if (s[i - 1].res == 0)flag++;
				if (s[i - 1].res == 1)flag--;
			}
			if (equal_num != 0) {
				if (s[i - 1].res == 0)equal_num0++;
				if (s[i - 1].res == 1)equal_num1++;
				flag = flag + equal_num0 - equal_num1;
				equal_num = 0;
				equal_num0 = 0;
				equal_num1 = 0;
			}
			if (flag >= num) {
				num = flag;
				ret = s[i].y;
			}
		}
	}
	printf("%d", ret);

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

卜凡.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值