GYM 101147 K.Touristic Trip(概率DP)

来源:互联网 发布:免root的手机数据恢复 编辑:程序博客网 时间:2024/06/06 14:39

Description
有n个城市(编号0~n-1),m种明信片(编号0~m-1),当前在i城市旅游下一次去j城市旅游的概率是P[i][j],当前在i城市送第j种明信片给父母的概率是C[i][j],现在给出旅游K个城市的过程中送出的明信片的序列a[i],问旅程送出明星片满足该序列的条件下在Z城市送出该序列中第Q张明星片的概率,初始在城市0
Input
第一行一整数T表示用例组数,每组用例首先输入五个整数n,m,K,Q,Z分别表示城市数量,明星片数量,旅行的城市数,要查询明星片在序列中的编号和的城市编号,之后一个n*n矩阵A和一个n*m矩阵C,最后K个整数a[i]表示在旅游K个城市时送出的明信片(1<=n<=20,1<=m<=10,1<=K<=15,0<=Q < K,0<=Z < n)
Output
输出在送出明星片序列满足所给序列的条件下在Z城市送出第Q张明星片的概率
Sample Input
1
3 3 3 2 1
0.00 0.75 0.25
0.10 0.00 0.9
0.1 0.9 0.00
0.2 0.3 0.5
0.1 0.01 0.89
0.2 0.3 0.5
0 1 2
Sample Output
0.889
Solution
条件概率,P(B|A)=P(AB)/P(A)
dp[i][j]表示在旅行的第i个城市是城市j且送出的是第a[i]种的明星片的概率,则dp[0][a[0]]=C[0][a[0]],对于i从1到Q转移,转移方程dp[i][j]+=dp[i-1][k]*P[k][j]*C[j][a[i]],之后,求P(AB)需要的是dp[Q][Z],求P(B)需要的是dp[Q][j] (0<=j<=n-1),所以令dpp[Q][Z]=dp[Q][Z],dpp[Q][j]=0(j!=Z),之后dpp和dp按上面同样的转移方程从i=Q-1到K-1同时进行转移,最后P(AB)=sum{dpp[K-1][j]},P(B)=sum{dp[K-1][j]},0<=j<=n-1,两者相除即为答案
Code

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#include<queue>#include<map>#include<set>#include<ctime>using namespace std;typedef long long ll;#define INF 0x3f3f3f3fint T,n,m,K,Q,Z,a[22],flag[22];double P[22][22],C[22][22],dp[22][22],dpp[22][22];int main(){    freopen("trip.in","r",stdin);    scanf("%d",&T);    while(T--)    {        scanf("%d%d%d%d%d",&n,&m,&K,&Q,&Z);        for(int i=0;i<n;i++)            for(int j=0;j<n;j++)                scanf("%lf",&P[i][j]);        for(int i=0;i<n;i++)            for(int j=0;j<m;j++)                scanf("%lf",&C[i][j]);        memset(flag,0,sizeof(flag));        for(int i=0;i<K;i++)scanf("%d",&a[i]);        memset(dp,0,sizeof(dp));        memset(dpp,0,sizeof(dpp));        dp[0][0]=C[0][a[0]];        for(int i=1;i<=Q;i++)            for(int j=0;j<n;j++)                for(int k=0;k<n;k++)                    dp[i][j]+=(dp[i-1][k]*P[k][j]*C[j][a[i]]);        dpp[Q][Z]=dp[Q][Z];        for(int i=Q+1;i<K;i++)            for(int j=0;j<n;j++)                for(int k=0;k<n;k++)                    dp[i][j]+=(dp[i-1][k]*P[k][j]*C[j][a[i]]),dpp[i][j]+=(dpp[i-1][k]*P[k][j]*C[j][a[i]]);        double ans1=0,ans2=0;        for(int i=0;i<n;i++)            ans1+=dp[K-1][i],ans2+=dpp[K-1][i];        printf("%.3f\n",ans2/ans1);    }    return 0;}
0 0
原创粉丝点击