理解了Q巨的代码。模写了一发。
dp数组含义为在第j个城市发明信片序列第i张的概率。
按照发放顺序转移
对于条件概率的分子,我么可以知道在这个dp数组里面只能从dp[Q][Z]转移过去。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 double dp[30][30]; 6 double path[30][30]; 7 double send[30][30]; 8 int n[30]; 9 int main() 10 { 11 int T; 12 freopen("trip.in","r",stdin); 13 cin >>T; 14 while(T--){ 15 int N,M,K,Q,Z; 16 cin >> N >> M >> K >> Q >> Z; 17 Q++; 18 Z++; 19 for (int i = 1; i<=N; i++){ 20 for (int j = 1; j<=N; j++) 21 cin >> path[i][j]; 22 } 23 for (int i = 1; i<=N; i++){ 24 for (int j = 1; j<=M ; j++) 25 cin >> send[i][j]; 26 } 27 for (int i = 1; i<=K; i++){cin >> n[i];n[i]++;} 28 memset(dp,0,sizeof(dp)); 29 dp[1][1] = send[1][n[1]]; 30 for (int m = 2; m<=K; m++) 31 for (int now = 1; now<=N; now++ ){ 32 for (int f = 1; f <=N; f++) 33 dp[m][now] += dp[m-1][f]*path[f][now]; 34 dp[m][now]*=send[now][n[m]]; 35 } 36 double f1 = 0; 37 for (int i = 1; i<=N; i++) 38 f1+=dp[K][i]; 39 memset(dp,0,sizeof(dp)); 40 if (Q!=1||1==Z)dp[1][1] = send[1][n[1]]; 41 for (int m = 2; m<=K; m++) 42 for (int now = 1; now<=N; now++ ){ 43 for (int f = 1; f <=N; f++) 44 dp[m][now] += dp[m-1][f]*path[f][now]; 45 dp[m][now]*=send[now][n[m]]; 46 if (m==Q&&now!=Z) dp[m][now] = 0; 47 } 48 double f2 = 0; 49 for (int i = 1; i<=N; i++) 50 f2+=dp[K][i]; 51 printf("%.3f ",f2/f1); 52 } 53 return 0; 54 }