题意 : 给你两个表格,第一个表格是三种天气下出现四种湿度的可能性。第二个表格是,昨天出现的三种天气下,今天出现三种天气的可能性。然后给你这几天的湿度,告诉你第一天出现三种天气的可能性,让你求出最可能出现的天气序列 。
思路 : 定义第 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 }