|
|
|
@@ -118,6 +118,7 @@ mypair<int> cal(mypair<int> orgScore, mypair<int> competitionScore) |
|
|
|
|
|
|
|
今年把得分上限这个东西去掉了。理论上今年可以得很高很高分,但是我估计大部分比赛得分在400-600左右,最高估计1000左右。算法 借 鉴 了THUAI4,算法,换了个激活函数(正态CDF),感觉分数变化相对更好了一些? |
|
|
|
代码如下: |
|
|
|
|
|
|
|
```cpp |
|
|
|
#include <iostream> |
|
|
|
#include <algorithm> |
|
|
|
@@ -243,3 +244,89 @@ int main() |
|
|
|
`1000 - score`(x |
|
|
|
`ReLU(1000 - score)`(√ |
|
|
|
防止真的超过了 1000) |
|
|
|
|
|
|
|
## THUAI6 |
|
|
|
|
|
|
|
因为今年的对局得分是两局得分之和,所以会出现一定程度的“数值膨胀”,在这里调低了胜者得分权值,同时提高了比赛分差距悬殊阈值和天梯分差距悬殊阈值。同时由于今年得分的上限不好确定,所以负者失分的基础值变为与胜者的得分之差。 |
|
|
|
|
|
|
|
```c++ |
|
|
|
#include <iostream> |
|
|
|
#include <algorithm> |
|
|
|
#include <cmath> |
|
|
|
using namespace std; |
|
|
|
|
|
|
|
template <typename T> |
|
|
|
using mypair = pair<T, T>; |
|
|
|
|
|
|
|
// orgScore 是天梯中两队的分数;competitionScore 是这次游戏两队的得分 |
|
|
|
|
|
|
|
mypair<int> cal(mypair<int> orgScore, mypair<int> competitionScore) |
|
|
|
{ |
|
|
|
|
|
|
|
// 调整顺序,让第一个元素成为获胜者,便于计算 |
|
|
|
|
|
|
|
bool reverse = false; // 记录是否需要调整 |
|
|
|
|
|
|
|
if (competitionScore.first < competitionScore.second) |
|
|
|
{ |
|
|
|
reverse = true; |
|
|
|
} |
|
|
|
else if (competitionScore.first == competitionScore.second) |
|
|
|
{ |
|
|
|
if (orgScore.first == orgScore.second) // 完全平局,不改变天梯分数 |
|
|
|
{ |
|
|
|
return orgScore; |
|
|
|
} |
|
|
|
|
|
|
|
if (orgScore.first > orgScore.second) // 本次游戏平局,但一方天梯分数高,另一方天梯分数低,需要将两者向中间略微靠拢,因此天梯分数低的定为获胜者 |
|
|
|
{ |
|
|
|
reverse = true; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
reverse = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (reverse) // 如果需要换,换两者的顺序 |
|
|
|
{ |
|
|
|
swap(competitionScore.first, competitionScore.second); |
|
|
|
swap(orgScore.first, orgScore.second); |
|
|
|
} |
|
|
|
|
|
|
|
// 转成浮点数 |
|
|
|
mypair<double> orgScoreLf; |
|
|
|
mypair<double> competitionScoreLf; |
|
|
|
orgScoreLf.first = orgScore.first; |
|
|
|
orgScoreLf.second = orgScore.second; |
|
|
|
competitionScoreLf.first = competitionScore.first; |
|
|
|
competitionScoreLf.second = competitionScore.second; |
|
|
|
mypair<int> resScore; |
|
|
|
|
|
|
|
const double deltaWeight = 1000.0; // 差距悬殊判断参数,比赛分差超过此值就可以认定为非常悬殊了,天梯分数增量很小,防止大佬虐菜鸡的现象造成两极分化 |
|
|
|
|
|
|
|
double delta = (orgScoreLf.first - orgScoreLf.second) / deltaWeight; |
|
|
|
cout << "Tanh delta: " << tanh(delta) << endl; |
|
|
|
{ |
|
|
|
|
|
|
|
const double firstnerGet = 9e-6; // 胜利者天梯得分权值 |
|
|
|
const double secondrGet = 5e-6; // 失败者天梯得分权值 |
|
|
|
|
|
|
|
double deltaScore = 2100.0; // 两队竞争分差超过多少时就认为非常大 |
|
|
|
double correctRate = (orgScoreLf.first - orgScoreLf.second) / (deltaWeight * 1.2); // 订正的幅度,该值越小,则在势均力敌时天梯分数改变越大 |
|
|
|
double correct = 0.5 * (tanh((competitionScoreLf.first - competitionScoreLf.second - deltaScore) / deltaScore - correctRate) + 1.0); // 一场比赛中,在双方势均力敌时,减小天梯分数的改变量 |
|
|
|
cout << "correct: " << correct << endl; |
|
|
|
resScore.first = orgScore.first + round(competitionScoreLf.first * competitionScoreLf.first * firstnerGet * (1 - tanh(delta)) * correct); // 胜者所加天梯分 |
|
|
|
resScore.second = orgScore.second - round((competitionScoreLf.first - competitionScoreLf.second) * (competitionScoreLf.first - competitionScoreLf.second) * secondrGet * (1 - tanh(delta)) * correct); // 败者所扣天梯分 |
|
|
|
} |
|
|
|
|
|
|
|
// 如果换过,再换回来 |
|
|
|
if (reverse) |
|
|
|
{ |
|
|
|
swap(resScore.first, resScore.second); |
|
|
|
} |
|
|
|
|
|
|
|
return resScore; |
|
|
|
} |
|
|
|
``` |
|
|
|
|