Peter's Hobby
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 545 Accepted Submission(s): 237
Problem Description
Recently, Peter likes to measure the humidity of leaves. He recorded a leaf humidity every day. There are four types of leaves wetness: Dry , Dryish , Damp and Soggy. As we know, the humidity of leaves is affected by the weather. And there are only three kinds
of weather: Sunny, Cloudy and Rainy.For example, under Sunny conditions, the possibility of leaves are dry is 0.6.
Give you the possibility list of weather to the humidity of leaves.
The weather today is affected by the weather yesterday. For example, if yesterday is Sunny, the possibility of today cloudy is 0.375.
The relationship between weather today and weather yesterday is following by table:
Now,Peter has some recodes of the humidity of leaves in N days.And we know the weather conditons on the first day : the probability of sunny is 0.63,the probability of cloudy is 0.17,the probability of rainny is 0.2.Could you know the weathers of these days
most probably like in order?
Give you the possibility list of weather to the humidity of leaves.
The weather today is affected by the weather yesterday. For example, if yesterday is Sunny, the possibility of today cloudy is 0.375.
The relationship between weather today and weather yesterday is following by table:
Now,Peter has some recodes of the humidity of leaves in N days.And we know the weather conditons on the first day : the probability of sunny is 0.63,the probability of cloudy is 0.17,the probability of rainny is 0.2.Could you know the weathers of these days most probably like in order?
题目大意:有三种天气和四种湿度。给出在每种天气下四种湿度的概率,和天气之间的转移概率,如今给出一个n天的湿度序列,要求给出一个概率最大的天气序列。
思路:非常easy的概率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: ",++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 "); else if(ans[i]==1) printf("Cloudy "); else printf("Rainy "); } } return 0; }