这一题我开始还用贝叶斯公式推了半天木有推出来,后来看到正解是Markov model == 当初上机率的时候老师最后都没讲这个chapter。然后我看百度百科举得例子居然和题目是一种。
Markov模型讨论的是状态之间的转移概率,转移的时候只和当前状态有关,转移的概率矩阵不随时间变化,所以可以根据初始状态算出之后的某个状态的概率,题目里面的case是隐式Markov Model引入了两个随机过程。
Markov Model的性质是:Xn+1对于过去条件的几率分布只与Xn有关,所以题目里的概率就是直接相乘(我开始还在条件概率里面绕了好久==)
dp[i][x]=max(dp[i][x],dp[i-1][y]*q[y][x]*p[x][c]),dp[i][x]表示第i天的天气是x,y表示i-1天的天气。
然后再用pre[i][x]记录前驱,即上式中max的y,再递归打印路径即可。
注意这里面虽然给了第一天各种天气的概率,但是因为input还定了第一天的humidity,所以dp[1][x]=p*p[1][humidity[1]];相当于 P(A&&B)。之前把这个漏了,我还纳闷给第一天的湿度有啥用。><
#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include <ctype.h>
#include<map>
using namespace std;
//hdu 4865
const int maxn=50;
int T;
int n;
int humidity[maxn];
map<string,int>mp;
double p[3][4]={0.6,0.2,0.15,0.05,0.25,0.3,0.2,0.25,0.05,0.1,0.35,0.5};
double q[3][3]={0.5,0.375,0.125,0.25,0.125,0.625,0.25,0.375,0.375};
double dp[maxn][3];
int pre[maxn][3];
void initial()
{
mp["Dry"]=0;
mp["Dryish"]=1;
mp["Damp"]=2;
mp["Soggy"]=3;
}
void DP()
{
memset(dp,0,sizeof(dp));
memset(pre,0,sizeof(pre));
dp[1][0]=0.63*p[0][humidity[1]];//day 1 除了满足给定的天气还要满足humidity,相当于P(AB)
dp[1][1]=0.17*p[1][humidity[1]];
dp[1][2]=0.2*p[2][humidity[1]];
// cout<<dp[1][0]<<" " <<dp[1][1]<<" "<<dp[1][2]<<endl;
for(int i=2;i<=n;i++)
{
int c=humidity[i];
for(int x=0;x<3;x++)
{
for(int y=0;y<3;y++)
{
double tmp=dp[i-1][y]*q[y][x]*p[x][c];
if(tmp>dp[i][x])
{
dp[i][x]=tmp;
pre[i][x]=y;
}
}
}
}
}
void print(int n,int x)
{
string str[]={"Sunny","Cloudy","Rainy"};
if(n==1)
{
cout<<str[x]<<endl;
return;
}
print(n-1,pre[n][x]);
cout<<str[x]<<endl;
}
int main()
{
freopen("input.txt","r",stdin);
// freopen("data.txt","r",stdin);
// freopen("out1.txt","w",stdout);
initial();
scanf("%d",&T);
for(int t=1;t<=T;t++)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
string s;
cin>>s;
map<string,int>::iterator it;
it=mp.find(s);
int c=it->second;
humidity[i]=c;
}
//for(int i=1;i<=n;i++) cout<<humidity[i]<<endl;
DP();
int mx=0;
double tmp=dp[n][0];//之前把dp 和 tmp敲成了int,结果舍尾变成0了。。
for(int i=1;i<3;i++)
{
//cout<<dp[n][i]<<" "<<tmp<<endl;;
if(tmp<dp[n][i])
{
// cout<<"here"<<endl;
tmp=dp[n][i];
mx=i;
}
}
// cout<<mx<<endl;
printf("Case #%d:\n",t);
print(n,mx);
}
return 0;
}