1. 質問へのリンク: CCF 202012-2 期末予測最適しきい値
質問番号: | 202012-2 |
質問名: | 期末予測の最適閾値 |
制限時間: | 1.0秒 |
メモリ制限: | 512.0MB |
問題の説明: | トピックの背景安全指数が比較的大きな範囲内の整数であることを考慮すると、Xiaocai は自分が本当に安全であるかどうか確信が持てない可能性があるため、Dunton は安全指数 y を特定の予測結果に変換するためにしきい値 θ を設定することにしました - 「ハングします。セクション」または「失敗しない」。 安全指数が高いほど、Xiaocai が失敗する可能性が低くなるため、y≧θ の場合、Dundun は Xiaocai が安全であり、今学期に失敗しないと予測します。そうでない場合、y<θ の場合、Dundun は Xiaocai に次のようにアドバイスします。学期の終わりには失敗するだろうから、予測していなかったとは言わないでください。」 では、このしきい値はどのように設定すればよいでしょうか。Dun Dun は、過去から答えを見つける準備ができています。 トピックの説明具体的には、Dundon は前学期の m 人の生徒の安全指数を評価し、i (1≤i≤m) 人の生徒の安全指数は [0,108] の範囲の整数である yi であると同時に、学期の不合格は結果 ∈ 0,1 として記録されます。ここで、0 は不合格を意味し、1 は不合格ではないことを意味します。 これに対応して、Dundu は predictθ(y) を使用して、しきい値 θ に従って安全指数 y を変換した特定の予測結果を表します。 予測θ(y)={0(y<θ)1(y≥θ) 最後に、Dundon は次の式を設計して、最適なしきい値 θ ∗を計算しました。 θ ∗ =maxargmaxθ∈yi∑j=1m(予測θ(yj)==結果j) この式は、次の規則として同等に表現することもできます。
入力フォーマット標準入力からデータを読み取ります。 入力の最初の行には、正の整数 m が含まれています。 次に、m 行を入力します。ここで、i (1≤i≤m) 行には、スペースで区切られた 2 つの整数 yi と resulti が含まれます。意味は上記のとおりです。 出力フォーマット標準出力に出力します。 最適なしきい値 θ ∗を表す整数を出力します。 サンプル1入力サンプル 1 出力例 1 説明ルール 1 によると、最適なしきい値の選択範囲は 0、1、3、5、7 です。 θ=0 の場合、正しい予測の数は 4 です。 θ=1 の場合、正しい予測の数は 5 です。 θ=3 の場合、正しい予測の数は 5 です。 θ=5 の場合、正しい予測の数は 4 です。 θ=7 の場合、正解数は 3 です。 閾値として 1 または 3 が選択された場合、予測精度が最も高くなるため、 3 番目の規則によれば、θ ∗ =max1,3=3 です。 サンプル 2 入力サンプル 2 出力サブタスクテスト データの 70% が m≤200 を保証します。 すべてのテスト データは 2≤m≤10 5を保証します。 |
2. 問題分析:
問題分析を読んだ後、この問題の難しさはmmにありますm人の生徒yyy は繰り返される可能性があり、単純に構造体配列を使用してデータを表すことはできません。最初に、 iiのハッシュ テーブルを使用する必要があります。行iの生徒のyi y_iy私そして前学期の失敗resulti result_iresulti进行统计得出考虑重复安全指数的挂科情况,然后转存入一个vector动态数组进行从小到大排序,从小到大遍历递推得出阈值 θ ⩾ \theta \geqslant θ⩾当前安全指数 y i y_i yi时左侧预测正确的次数,即挂科情况为0的数量,最后从大到小遍历边递推得到阈值 θ ⩾ \theta \geqslant θ⩾当前安全指数 y i y_i yi时右侧预测正确的次数,即挂科情况为1的数量,边迭代得出最佳阈值 θ ∗ \theta^* θ∗。其中,由于迭代是从大到小进行,所以该方法直接满足多个阈值均可以达到最高准确率时,选取其中最大的规则。
3. C++代码程序实现:
#include <bits/stdc++.h>
using namespace std;
struct safetyIndex
{
int y,ones_result,zeros_result,zeros_left,ones_right;
safetyIndex()
{
zeros_result=0;
ones_result=0;
}
bool operator<(const safetyIndex& si)
{
return this->y<si.y;
}
};
int main()
{
int m,yi,result_i,zeros=0,ones=0,pred_true=-1,ans,theta;
scanf("%d",&m);
unordered_map<int,safetyIndex> y2result;
for (int i=0;i<m ;++i )
{
scanf("%d%d",&yi,&result_i);
y2result[yi].y=yi;
if (result_i==0)
{
++y2result[yi].zeros_result;
}
else
{
++y2result[yi].ones_result;
}
}
vector<safetyIndex> si;
for (auto ele:y2result)
{
si.push_back(ele.second);
}
sort(si.begin(),si.end());
si[0].zeros_left=0;
for (int i=1;i<si.size();++i )
{
zeros+=si[i-1].zeros_result;
si[i].zeros_left=zeros;
}
for (int i=si.size()-1; i>=0;--i )
{
ones+=si[i].ones_result;
ans=si[i].zeros_left+ones;
if (ans>pred_true)
{
pred_true=ans;
theta=si[i].y;
}
}
printf("%d",theta);
return 0;
}