hdu4418 概率dp+高斯消元(近日吐槽)
因为过年,好久没更博客了,最近要狂补题解了==
1.做了几天的概率dp,稍后还要写一篇概率dp和期望的总结,当然,下面几天的专题还是概率dp
2.接着还要整理一个漂亮的高斯消元模板=
3.最近打了几场cf还有其他bc、cc和gym的比赛,个别好题补一下题解
然后就是开下一个专题和继续打比赛==
---------------------------我是漂亮的分割线-------------------------------------
随处吐槽,完毕开始写本题题解
首先期望方程:
E[pos]=sgn((E[pos]+i)*p[i]) i=1-m
终点E[e]=0,这个形成环了就能想到高斯消元
也就是pos点的期望是由他所能到达的m个点的期望+到达这点经过的i个点,当然需要乘以概率,期望嘛==
如何转化两个方向的问题,只要另外加上n-2个点即可,比如012345这6个点变成了0123454321
如何判断不可到达,就是在bfs的时候注意一个是能不能bfs到,一个是概率为0的别忘了
下面就是解高斯消元,具体看代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<queue> 5 #include<algorithm> 6 using namespace std; 7 #define eps 1e-8 8 int row,col,num[205]; 9 double a[205][205],x[205],p[205]; 10 int cnt,N,m; 11 int Gauss() 12 { 13 int tr,tc,i,j,max_r; 14 //temp_row,temp_col 15 for (tr=0,tc=0;tr<row&&tc<col;tr++,tc++) 16 { 17 max_r=tr; 18 for (i=tr+1;i<row;i++) 19 if (fabs(a[i][tc])>fabs(a[max_r][tc])) max_r=i; 20 if (fabs(a[max_r][tc])<eps) return 0;//多解即无解 21 if (max_r!=tr) 22 { 23 for (j=tc;j<col;j++) 24 swap(a[tr][j],a[max_r][j]); 25 swap(x[tr],x[max_r]); 26 } 27 for (j=tc+1;j<col;j++) a[tr][j]/=a[tr][tc]; 28 x[tr]/=a[tr][tc]; a[tr][tc]=1;//消tc列 29 for (i=0;i<row;i++) 30 if (i!=tr) 31 { 32 x[i]-=x[tr]*a[i][tc]; 33 for (j=tc+1;j<col;j++) a[i][j]-=a[tr][j]*a[i][tc]; 34 a[i][tc]=0; 35 } 36 } 37 return 1; 38 } 39 void bfs(int s) 40 { 41 int i,t,tmp; 42 memset(num,-1,sizeof(num)); 43 queue<int>q; 44 cnt=0; num[s]=cnt++; 45 q.push(s); 46 while (!q.empty()) 47 { 48 t=q.front(); q.pop(); 49 for (i=1;i<=m;i++) 50 { 51 if (fabs(p[i])<eps) continue; 52 tmp=(t+i)%N; 53 if (num[tmp]==-1) 54 { 55 num[tmp]=cnt++; 56 q.push(tmp); 57 } 58 } 59 } 60 } 61 int main() 62 { 63 //E[pos]=sgn((E[pos+i]+i)*p[i]); 64 int T,n,s,e,d,i,j,t; 65 scanf("%d",&T); 66 while (T--) 67 { 68 scanf("%d%d%d%d%d",&n,&m,&e,&s,&d); 69 for (i=1;i<=m;i++) { 70 scanf("%lf",&p[i]); 71 p[i]/=100.0; 72 } 73 if (s==e) { 74 printf("0.00\n"); 75 continue; 76 } 77 N=2*n-2; 78 if (d==1) s=N-s; 79 bfs(s);//标号 80 if (num[e]==-1&&num[N-e]==-1) { 81 printf("Impossible !\n"); 82 continue; 83 } 84 row=col=cnt;//build 85 //row行,col列,a数组左边系数矩阵,x数组右边答案矩阵 86 memset(a,0,sizeof(a)); 87 memset(x,0,sizeof(x)); 88 for (i=0;i<N;i++) 89 if (num[i]!=-1) 90 { 91 if (i==e||i==N-e) { 92 a[num[i]][num[i]]=1; 93 x[num[i]]=0; 94 continue; 95 } 96 a[num[i]][num[i]]=1; 97 for (j=1;j<=m;j++) 98 { 99 t=(i+j)%N; 100 if (num[t]!=-1){ 101 a[num[i]][num[t]]+=-p[j]; 102 x[num[i]]+=j*p[j]; 103 } 104 } 105 } 106 if (Gauss()) printf("%.2lf\n",x[num[s]]); 107 else printf("Impossible !\n"); 108 } 109 return 0; 110 }