题目大意:有三种天气和四种湿度,给出在每种天气下四种湿度的概率,和天气之间的转移概率,现在给出一个n天的湿度序列,要求给出一个概率最大的天气序列。
思路:很简单的概率DP,转移概率和状态概率都给好了,设dp[i][j]表示第i天是第j种天气的最大概率,然后pre[i][j]来记录序列顺序。
假设第i-1天是第j1种天气,第i天是j2种天气,天气转移概率为p1[j1][j2],第i天的湿度为x,在第j2种天气下x湿度的概率为p2[j2][x],则有:
dp[i][j2]=max(dp[i-1][j1]*p1[j1][j2]*p2[j2][x]),记录最大值是由哪一个j1转移过来的,用pre[i][j2]记录。最后求得最大的dp[n][j],根据pre数组输出路径即可。
注:题目中说由于dp[n][j]可能很小,用double乘可能会掉精度,所以要用log,但是我直接乘也过了,可能是运气比较好吧,以后这种问题还是要多注意。
#include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> #include <math.h> #include <string> #include <map> #include <vector> #define maxn 55 using namespace std; double dp[55][3]; int pre[55][3]; map<string,int> mp; string str; double p1[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 p2[3][3]={0.5,0.375,0.125,0.25,0.125,0.625,0.25,0.375,0.375}; void init() { mp.insert(make_pair("Dry",0)); mp.insert(make_pair("Dryish",1)); mp.insert(make_pair("Damp",2)); mp.insert(make_pair("Soggy",3)); } int main() { int ncase,T=0; scanf("%d",&ncase); init(); while(ncase--) { printf("Case #%d:\n",++T); int n; scanf("%d",&n); cin>>str; for(int i=0;i<=n;i++) { for(int j=0;j<3;j++) dp[i][j]=0; } int lab=mp[str]; memset(pre,0,sizeof(pre)); dp[1][0]=0.63*p1[0][lab]; dp[1][1]=0.17*p1[1][lab]; dp[1][2]=0.2*p1[2][lab]; for(int i=2;i<=n;i++) { cin>>str; int lab=mp[str]; for(int j=0;j<3;j++) { for(int k=0;k<3;k++) { double pp=dp[i-1][k]*p2[k][j]*p1[j][lab]; if(pp>dp[i][j]) { dp[i][j]=pp; pre[i][j]=k; } } } } vector<int> ans; double mi=0; int po; for(int i=0;i<3;i++) { if(dp[n][i]>mi) { mi=dp[n][i]; po=i; } } ans.push_back(po); int now=n; while(now!=1) { po=pre[now][po]; ans.push_back(po); now--; } for(int i=n-1;i>=0;i--) { if(ans[i]==0) printf("Sunny\n"); else if(ans[i]==1) printf("Cloudy\n"); else printf("Rainy\n"); } } return 0; }
hdu 4865 Peter's Hobby(2014 多校联合第一场 E),布布扣,bubuko.com
hdu 4865 Peter's Hobby(2014 多校联合第一场 E)
原文地址:http://blog.csdn.net/dyx404514/article/details/38239085