$dp$。
这题的本质和求一个有向无环图的最长路径长度的路径是一样的。
$dp[i][j]$表示到第$i$天,湿度为$a[i]$,是第$j$种天气的最大概率。记录一下最大概率是$i-1$天哪一种天气推过来的,然后就可以得到路径了。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<ctime> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0); void File() { freopen("D:\in.txt","r",stdin); freopen("D:\out.txt","w",stdout); } template <class T> inline void read(T &x) { char c = getchar(); x = 0; while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } } double ts[5][5]={ { 0,0,0,0,0}, { 0, 0.6, 0.2, 0.15, 0.05}, { 0, 0.25, 0.3, 0.2, 0.25}, { 0, 0.05, 0.1, 0.35, 0.5}, }; double tt[5][5]={ { 0 , 0 , 0}, { 0 , 0.5, 0.375, 0.125 }, { 0 , 0.25, 0.125, 0.625 }, { 0 , 0.25, 0.375, 0.375 }, }; double dp[60][5]; int T,n,p[60][5],a[60],cas=1; int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) { char s[10]; scanf("%s",s); if(strcmp(s,"Dry")==0) a[i]=1; else if(strcmp(s,"Dryish")==0) a[i]=2; else if(strcmp(s,"Damp")==0) a[i]=3; else a[i]=4; } memset(p,-1,sizeof p); memset(dp,0,sizeof dp); dp[1][1]=ts[1][a[1]]*0.63; dp[1][2]=ts[2][a[1]]*0.17; dp[1][3]=ts[3][a[1]]*0.2; for(int i=2;i<=n;i++) { for(int j=1;j<=3;j++) { for(int k=1;k<=3;k++) { if(dp[i-1][k]*tt[k][j]*ts[j][a[i]]>dp[i][j]) { dp[i][j]=dp[i-1][k]*tt[k][j]*ts[j][a[i]]; p[i][j]=k; } } } } stack<int>S; double mx=0; int idx=0; for(int j=1;j<=3;j++) if(dp[n][j]>mx) mx=dp[n][j],idx=j; int now=idx, r=n; while(1) { S.push(now); now=p[r][now]; r--; if(now==-1) break; } printf("Case #%d: ",cas++); while(!S.empty()) { int x=S.top(); S.pop(); if(x==1) printf("Sunny "); else if(x==2) printf("Cloudy "); else printf("Rainy "); } } return 0; }