HDOJ 4865 Peter's Hobby(概率dp, viterbi)
2017-07-06 00:02
387 查看
原题链接
本题中,湿度是直接可观测的,隐藏的状态就是天气状态。(不过这里不太合适,天气状态也是可观测的)。
这里引入viterbi,是为了更形象的说明期间的涉及到的概率问题,并不是是说此题就是viterbi算法了。因为viterbi本质就是DP,除了HMM的decoding,还可以用在其他地方。
说了这么多,简单描述下viterbi算法。
式中,Vt(j)就表明在第t天天气状态为j(晴天,雨天,阴天)的概率。我们求得最后一天VT(j)的概率,选取最大值,然后根据btt(j)回溯每一天的天气状况。
aij, 天气状态转移概率;
bj(xt), emission matrix(发射矩阵),天气为j湿度为xt的概率。
这两个概率矩阵就是题目提供的两个概率矩阵。
这里说得比较浅陋,如果第一次接触,可能比较难懂,直接看代码吧。代码中为了把乘法转化为加法,利用了log。
题目描述
题目大意
给定不同天气的湿度概率矩阵,以及不同天气的状态转移矩阵。输入湿度序列,求此湿度序列所对应的最有可能的天气序列。题目分析
一道典型的概率dp题,或者叫viterbi算法。viterbi算法常用在HMM(隐马尔科夫模型)的三个基本问题中的问题二:decoding,即Given an observation sequence and an HMM, determine the most probable hidden state sequence。本题中,湿度是直接可观测的,隐藏的状态就是天气状态。(不过这里不太合适,天气状态也是可观测的)。
这里引入viterbi,是为了更形象的说明期间的涉及到的概率问题,并不是是说此题就是viterbi算法了。因为viterbi本质就是DP,除了HMM的decoding,还可以用在其他地方。
说了这么多,简单描述下viterbi算法。
式中,Vt(j)就表明在第t天天气状态为j(晴天,雨天,阴天)的概率。我们求得最后一天VT(j)的概率,选取最大值,然后根据btt(j)回溯每一天的天气状况。
aij, 天气状态转移概率;
bj(xt), emission matrix(发射矩阵),天气为j湿度为xt的概率。
这两个概率矩阵就是题目提供的两个概率矩阵。
这里说得比较浅陋,如果第一次接触,可能比较难懂,直接看代码吧。代码中为了把乘法转化为加法,利用了log。
AC代码
#include <iostream> #include <algorithm> #include <vector> #include <stack> #include <string> #include <cmath> #include <cstring> using namespace std; double a[3][3] = {0.5, 0.375, 0.125, 0.25, 0.125, 0.625, 0.25, 0.375, 0.375}; // transition probability double b[3][4] = {0.6, 0.2, 0.15, 0.05, 0.25, 0.3, 0.2, 0.25, 0.05, 0.10, 0.35, 0.50}; // emittion probability double dp[55][3]; // results int path[55][3]; // path of days int in[55]; // input, the humidity of leaves int solve(string leaves) { if (leaves == "Dry") return 0; if (leaves == "Dryish") return 1; if (leaves == "Damp") return 2; if (leaves == "Soggy") return 3; return -1; } string solve(int days) { if (days == 0) return "Sunny"; if (days == 1) return "Cloudy"; if (days == 2) return "Rainy"; return nullptr; } void print(stack<int> sta, int count) { //cout << "Case #" << count << endl; printf("Case #%d:\n", count); while (!sta.empty()) { int val = sta.top(); cout << solve(val) << endl; sta.pop(); } } void init() { dp[0][0] = log(0.63 * b[0][in[0]]); dp[0][1] = log(0.17 * b[1][in[0]]); dp[0][2] = log(0.2 * b[2][in[0]]); } int main() { int T, N, count = 0; cin >> T; while (T--) { count++; cin >> N; for (int i = 0; i < N; ++i) { string leaves; cin >> leaves; in[i] = solve(leaves); } init(); // init the fisrt day. for (int i = 1; i < N; ++i) { for (int j = 0; j < 3; j++) { double tmp = dp[i - 1][0< 4000 /span>] + log(a[0][j] * b[j][in[i]]); path[i][j] = 0; for (int k = 1; k < 3; ++k) { if (dp[i - 1][k] + log(a[k][j] * b[j][in[i]]) > tmp) { tmp = dp[i - 1][k] + log(a[k][j] * b[j][in[i]]); path[i][j] = k; } } dp[i][j] = tmp; } } double maxP = dp[N-1][0]; int maxN = 0; for (int i = 1; i < 3; i++) { if (dp[N-1][i] > maxP) { maxP = dp[N-1][i]; maxN = i; } } stack<int> sta; sta.push(maxN); for (int i = N - 1; i > 0; --i) { sta.push(path[i][maxN]); maxN = path[i][maxN]; } print(sta, count); } return 0; }
相关文章推荐
- [HDOJ 4865] Peter's Hobby [概率DP]
- HDOJ 4865 Peter's Hobby
- HDU 4865 Peter&#39;s Hobby --概率DP
- HDOJ 4865 Peter's Hobby(维特比算法、隐马尔科夫模型)
- hdu 4865 Peter's Hobby(概率dp)
- HDU 4865 Peter's Hobby(输出路径的dp)
- hdu 4865 Peter's Hobby(DP)
- hdu 4865 Peter's Hobby(概率dp)
- hdoj 5570 balls 【概率dp 求期望】
- hdu 4865 Peter's Hobby
- hdoj 5001 Walk 【概率DP】 【在步数限制下 求不经过一个点的概率】
- HDOJ 5001 walk 概率dp
- HDU 4865 Peter's Hobby(2014 多校联合第一场 E)(概率dp)
- hdoj 5001 概率dp
- hdu 4865 Peter's Hobby
- hdoj3853LOOPS【概率dp求期望】
- HDOJ4336Card Collector【概率dp求期望+状态压缩】
- hdu 4865 Peter's Hobby(2014 多校联合第一场 E)
- HDOJ 4815 Little Tiger vs. Deep Monkey(概率DP)
- 【HDOJ5955】Guessing the Dice Roll(概率DP,AC自动机,高斯消元)