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 }
View Code

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4418 

posted on 2015-03-01 21:23  xiao_xin  阅读(164)  评论(0编辑  收藏  举报

导航