因为考试中没有截图下来,所有只能说个大致的题意。
第一题是一题SQL语句转编程语言。如果拿了70分的话应该是没考虑group by 和之后的去重。如果拿了80分的话是没有考虑到需要size>0。
第二题其实是一题HMM,通过HMM前向算法就可以做出来。前向算法本质上属于动态规划的算法,也可以用DP去做。
第三题要自己根据题目给出的公式计算梯度。
第二题的思路其实和刘建平Pinard博客中的盒子与球的例子是一模一样的,这里转载下博客中关于这部分的内容,完整的博客请见:https://www.cnblogs.com/pinard/p/6955871.html
以及和HMM相关的四讲:
这里我们用隐马尔科夫模型HMM(一)HMM模型中盒子与球的例子来显示前向概率的计算。
我们的观察集合是:
V={红,白},M=2
我们的状态集合是:
Q={盒子1,盒子2,盒子3},N=3
而观察序列和状态序列的长度为3.
初始状态分布为:
状态转移概率分布矩阵为:
观测状态概率矩阵为:
球的颜色的观测序列:
O={红,白,红}
按照前向算法。首先计算时刻1三个状态的前向概率:
时刻1是红色球,隐藏状态是盒子1的概率为:
隐藏状态是盒子2的概率为:
隐藏状态是盒子3的概率为:
现在我们可以开始递推了,首先递推时刻2三个状态的前向概率:
时刻2是白色球,隐藏状态是盒子1的概率为:
隐藏状态是盒子2的概率为:
隐藏状态是盒子3的概率为:
继续递推,现在我们递推时刻3三个状态的前向概率:
时刻3是红色球,隐藏状态是盒子1的概率为:
隐藏状态是盒子2的概率为:
隐藏状态是盒子3的概率为:
最终我们求出观测序列:O={红,白,红}的概率为:
按照盒子与球的例子,其实笔试中的第二题思路是一样的。
测试用例如下:
输入:
0.4 0.3 0.2 0.1
0.5 0.2 0.2 0.1
0.1 0.4 0.1 0.4
0.3 0.1 0.3 0.3
0.2 0.4 0.2 0.2
0.05 0.10 0.20 0.30 0.35
0.08 0.15 0.25 0.35 0.17
0.15 0.25 0.30 0.20 0.10
0.20 0.40 0.20 0.15 0.05
D B B A
输出:
-2.5928
代码:
//
// Created by Ginray on 2019/3/31.
//
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <iostream>
# include <set>
# include <map>
using namespace std;
int main() {
double a, b, c, d;
double data[5][5];
double reward[5][5];
scanf("%lf %lf %lf %lf", &a, &b, &c, &d);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++)
scanf("%lf", &data[i][j]);
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++)
scanf("%lf", &reward[i][j]);
}
char now[50];
long double ans = 0;
while (scanf("%s", &now) != EOF) {
int position;
if (strcmp(now, "S") == 0)
position = 0;
else if (strcmp(now, "A") == 0)
position = 1;
else if (strcmp(now, "B") == 0)
position = 2;
else if (strcmp(now, "C") == 0)
position = 3;
else if (strcmp(now, "D") == 0)
position = 4;
a = a * reward[0][position];
b = b * reward[1][position];
c = c * reward[2][position];
d = d * reward[3][position];
double new_a = a * data[0][0] + b * data[1][0] + c * data[2][0] + d * data[3][0];
double new_b = a * data[0][1] + b * data[1][1] + c * data[2][1] + d * data[3][1];
double new_c = a * data[0][2] + b * data[1][2] + c * data[2][2] + d * data[3][2];
double new_d = a * data[0][3] + b * data[1][3] + c * data[2][3] + d * data[3][3];
a = new_a;
b = new_b;
c = new_c;
d = new_d;
ans = a + b + c + d;
// printf("%.4Lf\n", ans);
// printf("%.4Lf\n", log10(ans));
}
ans = log10(ans);
printf("%.4Lf\n", ans);
}