CCF期末预测之最 佳阈值

本文探讨了一种高效算法,通过前缀后缀计数法寻找在给定序列中,预测学生考试结果的最佳阈值,以达到最高正确率。两种C++实现方式对比,暴力求解与巧妙优化的效率和复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最佳居然发不出来

题目背景

在这里插入图片描述

题目描述

在这里插入图片描述

输入格式

在这里插入图片描述

输出格式

在这里插入图片描述

样例

输入

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

输出

3

C++解答

我自己想的当然还是暴力求解,把所有y都当成阈值遍历一遍,找到最大正确率的阈值,不知道为啥只得了50分

#include<iostream>
using namespace std;
int main()
{
    int n;
    int a=0;
    int max_num=0,max_a=0;
    cin>>n;
    int y[n];
    int result[n];
    for(int i=0;i<n;i++){
        cin>>y[i]>>result[i];
    }
    for(int i=0;i<n;i++){
        a=y[i];
        int num=0;
        for(int j=0;j<n;j++){
            int result_predict;
            if(y[j]<a) result_predict=0;
            else result_predict=1;
            if(result_predict==result[j]) num++;
        }
        if(num>=max_num) {
            max_num=num;
            max_a=a;
        }
    }
    cout<<max_a;
    return 0;
}

发现了一个前缀后缀的巧妙方法
先把阈值进行排序,通过计算每个值在序列中前面为0,后面为1的个数(真实),对于一个阈值来说自己预测的肯定是前面都为0后面都为1,因此真实的个数和最多的就是最佳阈值

#include<iostream>
#include<algorithm>
using namespace std;
pair<int,int> pii[100005];      //pair数组储存信息,每个pair存储一个同学的y和result
int pre0[100005];               //记录该位置及前面的result为0的个数(前缀和)
int rear1[100005];              //记录该位置及后面的result为1的个数(后缀和)
int k = -1,ma = 0;              //k用来记录最佳阈值,ma用来存储最佳阈值对应的预测成国公数目
int main(){
    int m;
    cin>>m;                     //输入m
    pii[0] = pair<int,int>(-1,-1);
    for(int i = 1;i <= m;++i)   //初始化pii数组
        cin>>pii[i].first>>pii[i].second;
    sort(pii + 1,pii + 1 + m);  //将所有学生信息按照阈值从小到大排序,方便后续前缀后缀和的操作
    for(int i = 1;i <= m;++i)            //记录前缀0个数
        if(pii[i].second == 0)
            pre0[i] = pre0[i - 1] + 1;
        else
            pre0[i] = pre0[i - 1];
    for(int i = m;i >= 1;--i)           //记录后缀1个数
        if(pii[i].second == 1)
            rear1[i] = rear1[i + 1] + 1;
        else
            rear1[i] = rear1[i + 1];
    for(int i = 1;i <= m;++i){          //最终处理
        if(pii[i].first == pii[i - 1].first)
            continue;                   //如果有阈值相同的情况,那么在相同区间的第一个位置统计了,直接跳过
        if(ma <= pre0[i - 1] + rear1[i])//更新k和ma
            ma = pre0[i - 1] + rear1[i],k = pii[i].first;
    }
    cout<<k;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值