题意:第i天的天气会一定概率地影响第i+1天的天气,也会一定概率地影响这一天的湿度.概率在表中给出。给出n天的湿度,推测概率最大的这n天的天气。
分析:这是引自机器学习中隐马尔科夫模型的入门模型,其实在这里直接DP就可以了
定义:dp[i][j]为第i天天气为j(0,1,2分别表示三个天气)的概率,path[i][j]记录路径,path[i][j] = k 意思是前一天天气为k时,这一天有最大的概率是天气j。
做一个三重循环,对于每天,枚举今天的天气,再在里面枚举昨天的天气,则有:
dp[i][j] = max(dp[i-1][k]*yto[k][j]*wtoh[j][humi[i]])
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <string> #define eps 1e-4 using namespace std; string weather[4] = {"Sunny","Cloudy","Rainy"}; double yto[3][3]={{0.5,0.375,0.125},{0.25,0.125,0.625},{0.25,0.375,0.375}}; double wtoh[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}}; int humi[55],path[55][3],ans[55]; double dp[55][4]; int gethum(string ss) { if(ss == "Dry") return 0; else if(ss == "Dryish") return 1; else if(ss == "Damp") return 2; else return 3; } int main() { int t,cs = 1,i,j,n,k; string ss; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=0;i<n;i++) { cin>>ss; int hum = gethum(ss); humi[i] = hum; } for(i=0;i<=n;i++) for(j=0;j<3;j++) dp[i][j] = 0.0; memset(path,0,sizeof(path)); dp[0][0] = 0.63*wtoh[0][humi[0]]; dp[0][1] = 0.17*wtoh[1][humi[0]]; dp[0][2] = 0.20*wtoh[2][humi[0]]; for(i=1;i<n;i++) { for(j=0;j<3;j++) //today's weather { for(k=0;k<3;k++) //yesterday's weather { double P = dp[i-1][k]*yto[k][j]*wtoh[j][humi[i]]; if(P > dp[i][j]) { dp[i][j] = P; path[i][j] = k; } } } } int now = 0; for(i=0;i<3;i++) { if(dp[n-1][i] > dp[n-1][now]) now = i; } ans[n-1] = now; for(i=n-2;i>=0;i--) { now = path[i+1][now]; ans[i] = now; } printf("Case #%d:\n",cs++); for(i=0;i<n;i++) cout<<weather[ans[i]]<<endl; } return 0; }