题目链接

题意 : 给你两个表格,第一个表格是三种天气下出现四种湿度的可能性。第二个表格是,昨天出现的三种天气下,今天出现三种天气的可能性。然后给你这几天的湿度,告诉你第一天出现三种天气的可能性,让你求出最可能出现的天气序列 。

思路 : 定义第 i 天叶子湿度为hum[i]。第 i 天,天气为 j 的最大概率为dp[i][j]。wealea[i][j]表示天气为 i 叶子为j的概率,weawea[i][j]表示今天天气为 i 明天天气为j的概率,st[i]表示第一天天气为i的概率。pre[i][j]: 第i天,天气为j时,前一天最可能的天气 。fir[i]表示第1天天气为 i 的概率。

对于存在的叶子序列{a1,a2......an},存在一个天气序列{b1,b2......bn},那么总的概率dp[n][j]=max(fir[b1]*wealea[b1][a1]*weawea[b1][b2]*wealea[b2][a2]*......* weawea[bn-1][bn]*wealea[bn][an])。数据太小可能会丢失精度,所以可以用log将乘法转化成加法,即log()=log(fir[b1])+log(wealea[b1][a1])+log(weawea[b1][b2])+log(wealea[b2][a2])+......+log(weawea[bn-1][bn])+log(wealea[bn][an])。求log()的最大值对应的序列就是天气序列。

 

官方题解:

  1 //E
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <vector>
  5 #include <iostream>
  6 #include <string>
  7 #include <algorithm>
  8 #include <cmath>
  9 
 10 using namespace std ;
 11 
 12 string str ;
 13 vector<int>vec ;
 14 double wealea[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}} ;
 15 double weawea[3][3] = {{0.5,0.375,0.125},{0.25,0.125,0.625},{0.25,0.375,0.375}} ;
 16 double fir[3] = {0.63,0.17,0.2} ;
 17 double dp[53][5] ;
 18 double f[53][5] ;
 19 int pre[53][5] ;
 20 int hum[53] ;
 21 
 22 void solve()
 23 {
 24     for(int i = 0 ; i < 3 ; i++)
 25         fir[i] = log(fir[i]) ;
 26     for(int i = 0 ; i < 3 ; i++)
 27         for(int j = 0 ; j < 3 ; j ++)
 28             weawea[i][j] = log(weawea[i][j]) ;
 29 }
 30 void Init()
 31 {
 32     memset(pre,-1,sizeof(pre)) ;
 33     memset(f,0,sizeof(f)) ;
 34     for(int i = 0 ; i < 53 ; i++)
 35         for(int j = 0 ; j < 3 ; j++)
 36             dp[i][j] = -9999999 ;
 37     vec.clear() ;
 38 }
 39 int main()
 40 {
 41     int T, n ;
 42     cin >> T ;
 43     solve() ;
 44     for(int i = 1 ; i <= T ; i++)
 45     {
 46         cin >> n ;
 47         Init() ;
 48         for(int j = 0 ; j < n ; j++)
 49         {
 50             cin >> str ;
 51             if(str == "Dry") hum[j] = 0 ;
 52             else if(str == "Dryish") hum[j] = 1 ;
 53             else if(str == "Damp") hum[j] = 2 ;
 54             else if(str == "Soggy") hum[j] = 3 ;
 55         }
 56         for(int j = 0 ; j < n ; j++)
 57         {
 58             double x = 0 ;
 59             for(int k = 0 ; k < 3 ; k++)
 60             {
 61                 f[j][k] = wealea[k][hum[j]] ;
 62                 x += f[j][k] ;
 63             }
 64             for(int k = 0 ; k < 3 ; k++)
 65                 f[j][k] /= x ;
 66         }
 67         for(int j = 0 ; j < n  ;j++)
 68             for(int k = 0 ; k < 3 ; k++)
 69             f[j][k] = log(f[j][k]) ;
 70         for(int j = 0 ; j < 3 ; j++)
 71             dp[0][j] = f[0][j] + fir[j] ;
 72          for(int j = 1 ; j < n ; j ++)
 73             for(int k = 0; k < 3 ; k++)//今天
 74                 for(int h = 0; h < 3 ; h++)//昨天
 75                 {
 76                     double x1 = dp[j-1][h]+weawea[h][k]+f[j][k];
 77                     if(dp[j][k] < x1)
 78                     {
 79                         dp[j][k] = x1;
 80                         pre[j][k] = h;
 81                     }
 82                 }
 83         double maxx = -9999999 ;
 84         int s = 0,e = n-1 ;
 85         for(int j = 0 ; j < 3 ; j++)
 86         {
 87             if(dp[n-1][j] > maxx)
 88             {
 89                 maxx = dp[n-1][j] ;
 90                 s = j ;
 91             }
 92         }
 93         while(pre[e][s] != -1)
 94         {
 95             vec.push_back(s) ;
 96             s = pre[e][s] ;
 97             e -- ;
 98         }
 99         vec.push_back(s) ;
100         cout << "Case #"<<i<<":"<<endl ;
101         for(int j = n-1 ; j >= 0 ; j --)
102         {
103             if(vec[j] == 0) cout<<"Sunny"<<endl ;
104             if(vec[j] == 1) cout<<"Cloudy"<<endl ;
105             if(vec[j] == 2) cout<<"Rainy"<<endl ;
106         }
107     }
108     return 0 ;
109 }
View Code

 

posted on 2014-07-25 19:00  枫、  阅读(204)  评论(0编辑  收藏  举报