HDOJ 4865 Peter's Hobby(维特比算法、隐马尔科夫模型)
来源:互联网 发布:发表心情软件 编辑:程序博客网 时间:2024/05/20 07:19
由数据给出的形式,推得题目原型是这样一个模型——隐马尔科夫模型。
样例推导过程应该是这样的
每一天的天气组成都可以由前一天的天气组成推出,而由当天叶片湿度现象,可以倒推出当天最有可能的天气(解码)。
把整个题目情景作为一个马尔科夫过程,那么可知的是:天气的初始状态,每一天的叶片状态(观测状态)。题目要求求出最有可能的天气顺序(隐藏状态)。可以写出三个矩阵:
初始状态概率矩阵
隐含状态概率转移矩阵
观测状态概率放射矩阵
有了上面的推论,可以得出几点:
1.当前的隐藏状态天气组成s(i)和观测状态o(i)都只与前一天隐藏状态天气组成s(i-1)有关,而与在此之前所有的隐藏状态或是观测状态均无直接关系;
2.由一个初始隐藏状态天字组成s(1)、一个隐含状态概率转移矩阵和一个观测状态概率放射矩阵,可以得到任意一天的隐藏状态天气组成s(i)(i >= 1);
3.由当前观测状态o(i)、观测状态概率放射矩阵和上一次的隐藏状态天气组成s(i-1),通过最大似然估计法,可以倒推出隐藏状态天气组成s(i-1)中最有可能显现的状态(但最后一天是直接由概率推出状态)。
最大似然估计法:
并且在x的所有取值上,使似然函数的值最大化(一阶导数为0),即这个使可能性最大的x0值即被称为x的最大似然估计。
有了上面几个特点,发现这种算法是一种DP,状态转移方程(摘自维基百科):
相关链接:
[转载]发现一篇不错的学习隐马尔可夫模型的文章
http://blog.sciencenet.cn/blog-641976-533895.html
维特比算法 - 维基百科
http://zh.wikipedia.org/wiki/%E7%BB%B4%E7%89%B9%E6%AF%94%E7%AE%97%E6%B3%95
HMM学习笔记_3(从一个实例中学习Viterbi算法)
http://www.cnblogs.com/tornadomeet/archive/2012/03/24/2415889.html
最大似然估计 - 维基百科
http://zh.wikipedia.org/wiki/%E6%9C%80%E5%A4%A7%E4%BC%BC%E7%84%B6%E4%BC%B0%E8%AE%A1
AC代码:
#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <assert.h>#include <algorithm>#define MAX 1234567890#define MIN -1234567890#define eps 1e-8#define HIDSUM 3#define OBSSUM 4#define N 51using namespace std;///初始状态概率double pi[HIDSUM] = {0.63, 0.17, 0.2};///隐含状态概率转移矩阵double A[HIDSUM][HIDSUM] = { {0.5, 0.375, 0.125}, {0.25, 0.125, 0.625}, {0.25, 0.375, 0.375}};///观测状态概率放射矩阵double B[HIDSUM][OBSSUM] = { {0.6, 0.2, 0.15, 0.05}, {0.25, 0.3, 0.2, 0.25}, {0.05, 0.10, 0.35, 0.50}};char O[OBSSUM][10] = {"Dry", "Dryish", "Damp", "Soggy"};char S[HIDSUM][10] = {"Sunny", "Cloudy", "Rainy"};///dp[t][k]:第t天,最后状态落在S[k]观察到obs_seq[t]的最大概率double dp[N][HIDSUM];int rec[N][HIDSUM];int obs_seq[N];int hid_seq[N];int n;void Viterbi(){ int i, j, k; ///初始化第一天 for(k = 0; k < HIDSUM; k++) { dp[0][k] = log(pi[k]) + log(B[k][obs_seq[0]]); rec[0][k] = k; } for(i = 1; i < n; i++) { for(j = 0; j < HIDSUM; j++) { dp[i][j] = MIN; for(k = 0; k < HIDSUM; k++) { ///从昨天的三个状态过来,分别通过隐含状态概率矩阵转换, ///于是今天的每个状态都有三个概率,再对这九个概率, ///通过观测状态概率放射矩阵, ///求出每个隐含状态下该观测状态的最大概率, ///并记录在此情况下的上一次的隐含状态 double tmp = dp[i-1][k] + log(A[k][j]) + log(B[j][obs_seq[i]]); if(tmp > dp[i][j]) { dp[i][j] = tmp; rec[i][j] = k; } } } } double last = MIN; for(k = 0; k < HIDSUM; k++) { if(dp[n-1][k] > last) { last = dp[n-1][k]; hid_seq[n-1] = k; } } for(i = n - 2; i >= 0; i--) { hid_seq[i] = rec[i+1][hid_seq[i+1]]; }}int check(char *o){ for(int s = 0; s < OBSSUM; s++) { if(strcmp(o, O[s]) == 0) return s; }}int main(){// freopen("data.in", "r", stdin); int t; scanf("%d", &t); for(int m = 1; m <= t; m++) { scanf("%d", &n); getchar(); for(int d = 0; d < n; d++) { char leaf[10]; gets(leaf); obs_seq[d] = check(leaf); } Viterbi(); printf("Case #%d:\n", m); for(int d = 0; d < n; d++) {printf("%s\n", S[hid_seq[d]]);} } return 0;}
- HDOJ 4865 Peter's Hobby(维特比算法、隐马尔科夫模型)
- HDOJ 4865 Peter's Hobby
- [HDOJ 4865] Peter's Hobby [概率DP]
- hdu 4865 Peter's Hobby (隐马尔可夫模型 dp)
- hdu 4865 Peter's Hobby(DP)
- HDOJ 4865 Peter's Hobby(概率dp, viterbi)
- hdu 4865 Peter's Hobby
- HDU 4865 Peter's Hobby
- hdu 4865 Peter's Hobby
- 隐马尔可夫模型(HMM) HDU4865 Peter's Hobby
- hdu 4865 Peter's Hobby(概率dp)
- Peter's Hobby
- hdu4865 Peter's Hobby
- HMM:隐马尔科夫模型-维特比算法
- 隐马尔科夫模型与维特比算法
- 隐马尔科夫模型之前向算法和维特比算法
- hdu 4865 Peter's Hobby(2014 多校联合第一场 E)
- HDU 4865 Peter's Hobby(输出路径的dp)
- Android 屏幕适配
- UVa 389 - Basically Speaking
- jqueryui textbox的使用
- 压缩感知学习入门
- 【PAT (Advanced Level)】1027. Colors in Mars (20)
- HDOJ 4865 Peter's Hobby(维特比算法、隐马尔科夫模型)
- USB口433MHz透传模块 数据传输模块 无线传感器模块
- java加密与解密
- hd 2163 Palindromes
- jQuery元素和浏览器窗口的尺寸
- 模板整理之线性同余方程组(逆元法)
- 快速Fibonacci数列,矩阵法
- 杭电 2099 整除的尾数
- windbg 常用命令详解