zoukankan      html  css  js  c++  java
  • 概率DP

    题号+推荐指数

     hdu4089 **

    View Code
     1 /*
     2 dp[i][j]表示队伍里有i个人,Tomato在j位置,到达目标状态的概率;
     3 j==1   dp[i][j]=dp[i][j]*p1+dp[i][i]*p2+p4;
     4 1<j<=k dp[i][j]=dp[i][j]*p1+dp[i][j-1]*p2+dp[i-1][j-1]*p3+p4;
     5 j> k   dp[i][j]=dp[i][j]*p1+dp[i][j-1]*p2+dp[i-1][j-1]*p3;
     6 {i>=j}
     7 化简:
     8 j==1   dp[i][j]=dp[i][i]*p21+p41;
     9 1<j<=k dp[i][j]=dp[i][j-1]*p21+dp[i-1][j-1]*p31+p41;
    10 j> k   dp[i][j]=dp[i][j-1]*p21+dp[i-1][j-1]*p31;
    11 p=1-p1;
    12 p21=p2/p;
    13 p31=p3/p;
    14 p41=p4/p;
    15 
    16 dp[1][1]=p41/(1-p21);
    17 */
    18 #include<cstdio>
    19 #include<cstring>
    20 #include<iostream>
    21 #include<algorithm>
    22 #include<vector>
    23 #include<cmath>
    24 #include<cstdlib>
    25 using namespace std;
    26 const double eps=1e-8;
    27 const int N=2000+10;
    28 int n,m,k;
    29 double dp[N][N];
    30 double p1,p2,p3,p4;
    31 int main(){
    32 
    33     while (~scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4)){
    34         if (p4<1e-5) {
    35             printf("0.00000\n");continue;
    36         }
    37         double p,p21,p31,p41;
    38         //if (1-p1<eps || p<eps) while(1);
    39         p=1-p1;p21=p2/p;p31=p3/p;p41=p4/p;
    40       //  if (1-p21<eps) while(1);
    41         dp[1][1]=p41/(1-p21);
    42         for (int i=2;i<=n;i++){
    43             double c1=p21,c2=p41;
    44             for (int j=2;j<=i;j++){
    45                 c1*=p21;
    46                 if (j<=k) c2=c2*p21+dp[i-1][j-1]*p31+p41;
    47                 else c2=c2*p21+dp[i-1][j-1]*p31;
    48             }
    49             //if (1-c1<eps) while (1);
    50             dp[i][n]=c2/(1-c1);
    51             dp[i][1]=dp[i][n]*p21+p41;
    52             for (int j=2;j<n;j++){
    53                 if(j<=k) dp[i][j]=dp[i][j-1]*p21+dp[i-1][j-1]*p31+p41;
    54                 else dp[i][j]=dp[i][j-1]*p21+dp[i-1][j-1]*p31;
    55             }
    56         }
    57         printf("%.5lf\n",dp[n][m]);
    58     }
    59     return 0;
    60 }
    61 
    62 /*
    63 2 2 1 0.5 0.2 0.3 0
    64 3 2 1 0.4 0.3 0.3 0
    65 4 2 3 0.16 0.16 0.68 0
    66 */

    poj2096  *

     1 View Code 
     2  /*
     3  题意:n个子系统,s种bug,每次选一个bug,问达到每个子系统至少找到一个bug,每种bug至少找到一个,找到任意子系统的任意种bug的概率是不变的;
     4  
     5  dp[i][j]表示已经包含i各子系统j种Bug的期望次数;
     6  则对于dp[i][j]的期望等于它到下一步的概率p*dp[下一步]的和,即sum{p*dp[下一步]}+1;
     7  
     8  dp[i][j]=1/(n*s){i*j*dp[i][j]+(n-i)*jdp[i+1][j]+i*(s-j)*dp[i][j+1]+(n-i)*(s-j)*dp[i+1][j+1]}+1;
     9  移项得:
    10  dp[i][j]={(n-i)*jdp[i+1][j]+i*(s-j)*dp[i][j+1]+(n-i)*(s-j)*dp[i+1][j+1]+n*s}/(n*s-i*j);
    11  
    12  */
    13  
    14  //BM:poj c++ AC,g++ WA
    15  #include<cstdio>
    16  #include<cmath>
    17  #include<iostream>
    18  #include<algorithm>
    19  #include<cstdlib>
    20  #include<cstring>
    21  using namespace std;
    22  int n,s;
    23  const int N=1000+10;
    24  double dp[N][N];
    25  const double eps=1e-10;
    26  int main(){
    27  while (cin>>n>>s){
    28      memset(dp,0,sizeof(dp));
    29      dp[n][s]=0;
    30      double up=n*s;
    31      for (int i=n;i>=0;i--){
    32          for (int j=s;j>=0;j--){
    33              if (i==n && j==s) continue;
    34              dp[i][j]=(n-i)*j*dp[i+1][j]+i*(s-j)*dp[i][j+1]+(n-i)*(s-j)*dp[i+1][j+1]+up;
    35              dp[i][j]/=(double)up-i*j;
    36          }
    37      }
    38      printf("%.4lf\n",dp[0][0]);
    39  }
    40  
    41  return 0;
    42  }

     zoj3329  *

     1 View Code 
     2  /*
     3  题意:长度为n的条形棋盘,3个骰子,每个有ki个面,每次同时扔,每次走3个骰子的数总和,
     4  从0开始走,但如果分别是a,b,c则返回0;
     5  问走完棋盘期望的步数;
     6  设e[i]表示在i位走完棋盘的期望,
     7  e[n+1]=0;tmp=1/(k1*k2*k3);
     8  e[n]=(1-tmp)e[n+1]+tmp*e[0]+1;
     9  e[i]=pj*e[i+1]+p*e[i+2]+...p*e[n+1]+e[0]+1;
    10  从方程中可以看出e[i]都是由e[j](j>i)和e[0]推出;
    11  而e[n]可以由e[0]和常数项表示,
    12  e[n-1]=p*e[n]+p*e[0]+1;
    13  那么e[n-1]也可以由e[0]和常数项表示;
    14  同理e[i]都可以由e[0]和常数项表示;
    15  最后e[0]=p*e[0]+c; 
    16  */
    17  #include<cstdio>
    18  #include<cstring>
    19  #include<cstdlib>
    20  #include<iostream>
    21  #include<algorithm>
    22  #include<cmath>
    23  #include<vector>
    24  using namespace std;
    25  int n,k1,k2,k3,a,b,c;
    26  double e[510];
    27  double p[510][510];
    28  double x[510],y[510];
    29  int main(){
    30      int T;scanf("%d",&T);
    31      while (T--){
    32          scanf("%d%d%d%d%d%d%d",&n,&k1,&k2,&k3,&a,&b,&c);
    33          memset(p,0,sizeof(p));
    34          double tmp=(double)1/(k1*k2*k3);
    35          for (int i=0;i<=n;i++){
    36              for (int j=1;j<=k1;j++) for (int k=1;k<=k2;k++)
    37              for (int l=1;l<=k3;l++){
    38                  if (j==a && k==b && l==c) {
    39                      p[i][0]+=tmp;continue;
    40                  }
    41                  if (i+j+k+l>n) p[i][n+1]+=tmp;
    42                  else p[i][i+j+k+l]+=tmp;
    43              }
    44          }
    45          memset(e,0,sizeof(e));
    46          memset(x,0,sizeof(x));
    47          memset(y,0,sizeof(y));
    48          int up=k1+k2+k3;
    49          x[n+1]=0;y[n+1]=0;
    50          for (int i=n;i>=0;i--){
    51              for (int j=1;j<=up;j++){
    52                  x[i]+=p[i][i+j]*x[i+j];
    53                  y[i]+=p[i][i+j]*y[i+j];
    54                  if(i+j>n) break;
    55              }
    56              x[i]+=tmp;
    57              y[i]+=1;
    58          }
    59          double ans=0;
    60          ans=y[0]/(1-x[0]);
    61          printf("%.18lf\n",ans);
    62      }
    63      return 0;
    64  }

    zoj3582 *

     1 /*
     2 题意:盒子两边各有n个黑洞,每个黑洞每天能亮的概率为p,一旦亮就恒为亮,
     3 求两边至少都亮m个的期望;
     4 设dp[i][j]表示左边i个亮,右边j个亮到达目标的期望;
     5 则dp[i][j]=1+sigma{C(n-i,x)*p^x*(1-p)^(n-i-x) * C(n-j,y)*p^y*(1-p)^(n-j-y)*dp[i+x][j+y]};
     6 范围:i+x<=m,j+y<=m;
     7 dp[i][j]=0;i>=m&& j>=m;
     8 然后就递推;
     9 */
    10 #include<cstdio>
    11 #include<iostream>
    12 #include<algorithm>
    13 #include<cmath>
    14 #include<vector>
    15 #include<cstdlib>
    16 #include<cstring>
    17 using namespace std;
    18 const int N=51;
    19 double p,dp[N][N],C[N][N];
    20 int n,m;
    21 //C[i][j]表示C(i,j)*p^i*(1-p)^(i-j);
    22 void init(){
    23     memset(C,0,sizeof(C));
    24     C[0][0]=1;
    25     C[1][0]=1.0-p;C[1][1]=p;
    26     for (int i=2;i<=n;i++){
    27         C[i][0]=C[i-1][0]*(1.0-p);
    28         for (int j=1;j<=i;j++){
    29             C[i][j]=C[i-1][j]*(1.0-p)+C[i-1][j-1]*p;
    30         }
    31     }
    32 }
    33 double cal(int sx,int sy,int x,int y){
    34     double ret=1;
    35     ret=C[n-sx][x-sx]*C[n-sy][y-sy];
    36     return ret;
    37 }
    38 int main(){
    39     while (~scanf("%d%d%lf",&n,&m,&p),n+m){
    40         memset(dp,0,sizeof(dp));
    41         init();
    42         for (int i=m;i>=0;i--){
    43             for (int j=m;j>=0;j--){
    44                 if (i==m && j==m) continue;
    45                 double tmp=1;
    46                 for (int x=i;x<=m;x++){
    47                     for (int y=j;y<=m;y++){
    48                         if (x==i && y==j) continue;
    49                         tmp+=cal(i,j,x,y)*dp[x][y];
    50                     }
    51                 }
    52                 dp[i][j]=tmp/(1-cal(i,j,i,j));
    53             }
    54         }
    55         printf("%.6lf\n",dp[0][0]);
    56     }
    57     return 0;
    58 }

    hdu3853  *

     1 #include<cmath>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<cstdlib>
     5 #include<cstdio>
     6 #include<algorithm>
     7 using namespace std;
     8 const int MAXN=1010; 
     9 struct node{
    10     double g[3]; 
    11     void input(){
    12         for (int i=0;i<3;i++) 
    13         scanf("%lf",&g[i]); 
    14     } 
    15 }mp[MAXN][MAXN]; 
    16 int n,m; 
    17 double dp[MAXN][MAXN]; 
    18 int main()
    19 {
    20     while (~scanf("%d%d",&n,&m)){
    21         for (int i=1;i<=n;i++){
    22             for (int j=1;j<=m;j++)
    23             mp[i][j].input(); 
    24         } 
    25         memset(dp,0,sizeof(dp));
    26         for (int i=n;i>=1;i--){
    27             for (int j=m;j>=1;j--){
    28                 if (i==n && j==m) continue; 
    29                 if (mp[i][j].g[0]==1) continue; 
    30                 dp[i][j]=(mp[i][j].g[1]*dp[i][j+1]+mp[i][j].g[2]*dp[i+1][j]+2)/(1-mp[i][j].g[0]); 
    31             } 
    32         } 
    33         printf("%.3f\n",dp[1][1]); 
    34         
    35         
    36     } 
    37     return 0; 
    38 } 

     hdu4035  **

     1 View Code 
     2  /*
     3  题意:给你一棵树,每个结点都有ki,ei,分别表示返回1的概率和逃离的概率,从起点1出发
     4  每经过一条边花费为1,问逃离的期望;BM:每个点往其他点的概率是相同的; 
     5   
     6  设e[i]表示在i结点平均还需要e[i]步可以逃离;
     7  8  tmp=(100-ki-ei)/100;
     9  e[i]=ki*e[1]+ei*0+tmp*( sigma{(1/m)*(e[j]+1)} );其中m是与i相连的个数,j是与i相连的结点;
    10  显然方程中出现了环,消环:
    11  列出所有方程,我们发现对于叶子结点,它需要父亲结点
    12  而对于非叶子结点它需要父亲结点外还需要它所有儿子结点;
    13  这样我们想到如果把一个非叶子结点的所有儿子的方程带入,就得到了一个只由e[1],e[fa],c,三项组成的方程:
    14  e[i]=ki*e[1]+ei*0+A*e[i]+B*e[fa]+C;
    15  e[i]=(ki*e[1]+B*e[fa]+C)/(1-A);
    16   
    17  这样这个非叶子结点就又可以看成叶子结点了,递推上去就ok了;
    18  BM:因为叶子结点的方程:e[i]=ki*e[i]+(1-ei-ki)*(e[fa]+1);
    19   
    20  
    21  类似树形dp的写法;
    22  x[i],y[i],z[i];分别记录对于i结点e[i],e[fa],c的系数; 
    23  */
    24  #include<cstdio>
    25  #include<cstring>
    26  #include<iostream>
    27  #include<algorithm>
    28  #include<cmath>
    29  #include<vector>
    30  #include<cstdlib>
    31  using namespace std;
    32  const int N=10000+10;
    33  const double eps=1e-10;//精度要高一点,不然会WA 
    34  int dcmp(double x){
    35      return x<-eps?-1:x>eps;
    36  }
    37  vector<int> g[N];
    38  int ki[N],ei[N];
    39  int n;
    40  double x[N],y[N],z[N];
    41  void dfs(int rt,int fa){
    42  
    43      int sz=g[rt].size();
    44      double tmp=(double)(100-ki[rt]-ei[rt])/100/sz;
    45      x[rt]=(double)ki[rt]/100;
    46      y[rt]=tmp;z[rt]=(double)(100-ki[rt]-ei[rt])/100;
    47      
    48      double prt=0;
    49      for (int i=0;i<sz;i++){
    50          int c=g[rt][i];
    51          if (c!=fa){
    52              dfs(c,rt);
    53              x[rt]+=tmp*(x[c]);
    54              prt+=tmp*(y[c]);//c的e[fa]就是e[rt],先存在prt中,最后做调整方程用; 
    55              z[rt]+=tmp*z[c];
    56          }
    57      }
    58      double t=(double)1-prt;
    59      x[rt]/=t;
    60      y[rt]/=t;
    61      z[rt]/=t;
    62  //    cout<<rt<<" "<<x[rt]<<" "<<y[rt]<<" "<<z[rt]<<endl; 
    63  }
    64  int main(){
    65      int T,cas=0;
    66      scanf("%d",&T);
    67      while (T--){
    68          scanf("%d",&n);
    69          for (int i=0;i<=n;i++) g[i].clear();
    70          for (int i=1;i<n;i++){
    71              int u,v;scanf("%d%d",&u,&v);
    72              g[u].push_back(v);
    73              g[v].push_back(u);
    74          }
    75          for (int i=1;i<=n;i++){
    76              scanf("%d%d",&ki[i],&ei[i]);
    77          }
    78          memset(x,0,sizeof(x));memset(y,0,sizeof(y));
    79          memset(z,0,sizeof(z));
    80          dfs(1,0);
    81          printf("Case %d: ",++cas);
    82          if (dcmp((double)1-x[1])==0) printf("impossible\n");
    83          else{
    84              double ans=z[1]/(1-x[1]);
    85              printf("%.10lf\n",ans);
    86          }
    87      }
    88      return 0;
    89  }

    hdu2262  **

      1 /*
      2 题意:n*m的地图,从起点出发,到终点,问期望走多少步;
      3 设dp[i*m+j]表示在(i,j)出发到达终点的期望步数;
      4 然后建立方程就好了; 
      5 很简单的题意,但有几点要注意的地方:
      6 有多个终点;
      7 有些地方是走不到的,所以可以先bfs扫一遍把能走到的位置标号,
      8 然后建图,这样就不会遇到我在做时遇到的问题;
      9 
     10 我遇到的问题,直接按照i*m+j建立了n*m个方程,n*m个变量的方程组;
     11 由于本题的特殊性,解方程组时,只会出现无解或唯一解的状况,不会出现无穷解;
     12 而且由于行列变换变成一个上三角方程组后,但编号都会变化;
     13 也就是求出x[i]不是原先的x'[i]的值;
     14 
     15 但行列变换成一个斜线,就不会出现这个问题;
     16 也就是用gauss_jordan;  
     17 */
     18 #include<cstdio>
     19 #include<cstdlib>
     20 #include<cstring>
     21 #include<iostream>
     22 #include<algorithm>
     23 #include<vector>
     24 #include<queue>
     25 #include<cmath>
     26 #define MP make_pair
     27 using namespace std;
     28 const int N=250;
     29 int n,m;
     30 char mz[20][20];
     31 const double eps=1e-8;
     32 int vis[N][N],dp[N][N];
     33 int sx,sy;
     34 typedef double Matrix[N][N];
     35 typedef pair<int,int> pii;
     36 queue<pii> q;
     37 const int dx[4]={0,1,0,-1};
     38 const int dy[4]={1,0,-1,0};
     39 Matrix A;
     40 void bfs(){
     41     while (!q.empty()) q.pop();
     42     memset(vis,0,sizeof(vis));
     43     for (int i=0;i<n;i++){
     44         for (int j=0;j<m;j++){
     45             if (mz[i][j]=='@'){
     46                 sx=i;sy=j;
     47             }
     48             if (mz[i][j]=='$'){
     49                 q.push(MP(i,j));
     50                 vis[i][j]=1;
     51             }
     52         }
     53     }
     54     while (!q.empty()){
     55         pii u=q.front();q.pop();
     56         for (int i=0;i<4;i++){
     57             int nx=u.first+dx[i],ny=u.second+dy[i];
     58             if (nx<0 || nx>=n || ny<0 || ny>=m || mz[nx][ny]=='#' || vis[nx][ny]) continue;
     59             vis[nx][ny]=1;
     60             q.push(MP(nx,ny));
     61         }
     62     }
     63 }
     64 void Make(){
     65     memset(A,0,sizeof(A));
     66     for (int i=0;i<n;i++){
     67         for (int j=0;j<m;j++){
     68             if (mz[i][j]=='#') continue;
     69             int u=i*m+j;
     70             if (mz[i][j]=='$'){
     71                 A[u][u]=1;
     72                 A[u][n*m]=0;
     73                 continue;
     74             }
     75 
     76             int cnt=0;
     77             for (int k=0;k<4;k++){
     78                 int nx=i+dx[k],ny=j+dy[k];
     79                 if (nx<0 || nx>=n || ny<0 || ny>=m || mz[nx][ny]=='#'|| vis[nx][ny]==0)
     80                     continue;
     81                 A[u][nx*m+ny]=1;
     82                 cnt++;
     83             }
     84             A[u][u]=-cnt;
     85             A[u][n*m]=-cnt;
     86         }
     87     }
     88 }
     89 int gauss_jordan(Matrix A,int n,int m){
     90     int i,j,k,r;
     91     for (i=0;i<n;i++){
     92         r=i;
     93         for (j=i+1;j<n;j++){
     94             if (fabs(A[r][i])<fabs(A[j][i])) r=j;
     95         }
     96         if (fabs(A[r][i])<eps) continue;
     97         if (r!=i) for (j=0;j<=m;j++) swap(A[r][j],A[i][j]);
     98            for (k=0;k<n;k++) if (k!=i){
     99              for (j=n;j>=i;j--) A[k][j]-=A[k][i]/A[i][i]*A[i][j];
    100         }
    101     }
    102     for (i=0;i<n;i++)if (fabs(A[i][i])<eps && fabs(A[i][m])>eps) return 0;
    103     return 1;
    104 }
    105 
    106 int main(){
    107     while (~scanf("%d%d",&n,&m)){
    108         for (int i=0;i<n;i++){
    109             scanf("%s",mz[i]);
    110         }
    111         bfs();
    112         Make();
    113         if (vis[sx][sy] && gauss_jordan(A,n*m,n*m)){
    114             printf("%.6lf\n",A[sx*m+sy][n*m]/A[sx*m+sy][sx*m+sy]);
    115         }else printf("-1\n");
    116     }
    117     return 0;
    118 }

    hdu3058 **

      1 /*
      2 题意:每次在串末等概率的加一个字母,问期望加几个字母使串包含指定的字母;
      3 如果刷过几道AC自动机,然后再联想到有向图上的DP,最多100个点,而且一定有解,直接gauss;
      4 本题就是简单题目了;
      5 
      6 
      7 */
      8 #include<cstdio>
      9 #include<cstdlib>
     10 #include<cstring>
     11 #include<iostream>
     12 #include<algorithm>
     13 #include<cmath>
     14 #include<vector>
     15 #include<map>
     16 #include<set>
     17 #include<queue>
     18 using namespace std;
     19 const int N=100+10;
     20 int SZ;
     21 struct AC{
     22     int ch[N][26];
     23     int sz,val[N],fail[N];
     24     queue<int> q;
     25     void init(){
     26         sz=1;memset(val,0,sizeof(val));
     27         memset(ch[0],0,sizeof(ch[0]));
     28     }
     29     void insert(char *s){
     30         int rt=0;
     31         for (int i=0;s[i];i++){
     32             int c=s[i]-'A';
     33             if (ch[rt][c]==0){
     34                 ch[rt][c]=sz;
     35                 memset(ch[sz],0,sizeof(ch[sz]));
     36                 sz++;
     37             }
     38             rt=ch[rt][c];
     39         }
     40         val[rt]=1;
     41     }
     42     void getfail(){
     43         while (!q.empty()) q.pop();
     44         for (int i=0;i<SZ;i++){
     45             int c=ch[0][i];
     46             if (c){ q.push(c);fail[c]=0; }
     47         }
     48         while (!q.empty()){
     49             int u=q.front();q.pop();
     50             for (int i=0;i<SZ;i++){
     51                 int c=ch[u][i];
     52                 if (!c){
     53                     ch[u][i]=ch[fail[u]][i];
     54                 }else {
     55                     int v=fail[u];
     56                     q.push(c);
     57                     fail[c]=ch[v][i];
     58                     val[c]|=val[fail[c]];
     59                 }
     60             }
     61         }
     62     }
     63     void check_print(){
     64         cout<<"****** "<<endl;
     65         for (int i=0;i<sz;i++){
     66             if (val[i]){
     67                 printf("%d %d\n",i,val[i]);
     68             }
     69         }
     70         cout<<"***** "<<endl;
     71     }
     72 }H;
     73 /////////////////建立AC自动机生产有向图/////////////
     74 typedef double Matrix[N][N];
     75 int n;
     76 Matrix A;
     77 void gauss(Matrix A,int n){///////////gauss消元/////
     78     /*
     79         cout<<"+++++ "<<endl;
     80         for (int i=0;i<n;i++){
     81             for (int j=0;j<=n;j++){
     82                 cout<<A[i][j]<<" ";
     83             }cout<<endl;
     84         }cout<<"+++++ "<<endl;
     85     */
     86     int i,j,r,c,id;
     87     for (r=0;r<n;r++){
     88         id=r;
     89         for (i=r+1;i<n;i++)if (fabs(A[id][r])<fabs(A[i][r])) id=i;
     90         if (id!=r)for (j=r;j<n;j++) swap(A[id][j],A[r][j]);
     91 
     92         for (i=r+1;i<n;i++){
     93             double tmp=A[i][r]/A[r][r];
     94             for (j=r;j<=n;j++){
     95                 A[i][j]-=tmp*A[r][j];
     96             }
     97         }
     98       /*  cout<<"+++++ "<<r<<endl;
     99         for (int i=0;i<n;i++){
    100             for (int j=0;j<=n;j++){
    101                 cout<<A[i][j]<<" ";
    102             }cout<<endl;
    103         }cout<<"+++++ "<<endl;
    104     */
    105     }
    106 
    107     for (i=n-1;i>=0;i--){
    108         for (j=n-1;j>i;j--){
    109             A[i][n]-=A[i][j]*A[j][n];
    110         }
    111         A[i][n]/=A[i][i];
    112     }
    113 }
    114 void work(){
    115     memset(A,0,sizeof(A));
    116     for (int i=0;i<H.sz;i++){
    117         if (H.val[i]){
    118             A[i][i]=1;
    119             A[i][H.sz]=0;
    120         }else {
    121             for (int j=0;j<SZ;j++){
    122                 int c=H.ch[i][j];
    123                 A[i][c]+=1;
    124             }
    125             A[i][i]+=-SZ;
    126             A[i][H.sz]=-SZ;
    127         }
    128     }
    129     /////////////构造方程组/////////
    130     gauss(A,H.sz);
    131     printf("%.2lf\n",A[0][H.sz]);
    132 
    133 }
    134 int main(){
    135     int T;scanf("%d",&T);
    136     while (T--){
    137         scanf("%d%d",&SZ,&n);
    138         H.init();
    139         for (int i=0;i<n;i++){
    140             char s[15];
    141             scanf("%s",s);
    142             H.insert(s);
    143         }
    144         H.getfail();
    145         //
    146        // H.check_print();
    147         //
    148         work();
    149     }
    150     return 0;
    151 }
    152 /*
    153 4
    154 26 4
    155 SHE
    156 HE
    157 HER
    158 OSHE
    159 
    160 */

     hdu3992 **

    View Code
      1 /*
      2 题意:每次在串末不同概率的加一个字母,问期望加几个字母使串包含指定任意一个的单词;
      3 同上;
      4 但是本题有可能出现无解的情况,但要么是有唯一解,要么无解,所以用了gauss_jordan化成了斜矩阵,
      5 这样写比较简单;但这样的gauss时间就稳定在O(n^3)了;
      6 
      7 
      8 */
      9 #include<cstdio>
     10 #include<cstdlib>
     11 #include<cstring>
     12 #include<iostream>
     13 #include<algorithm>
     14 #include<cmath>
     15 #include<vector>
     16 #include<map>
     17 #include<set>
     18 #include<queue>
     19 using namespace std;
     20 const int N=230+10;
     21 const int SZ=26;
     22 double p[30];
     23 struct AC{
     24     int ch[N][26];
     25     int sz,val[N],fail[N];
     26     queue<int> q;
     27     void init(){
     28         sz=1;memset(val,0,sizeof(val));
     29         memset(ch[0],0,sizeof(ch[0]));
     30     }
     31     void insert(char *s){
     32         int rt=0;
     33         for (int i=0;s[i];i++){
     34             int c=s[i]-'a';
     35             if (ch[rt][c]==0){
     36                 ch[rt][c]=sz;
     37                 memset(ch[sz],0,sizeof(ch[sz]));
     38                 sz++;
     39             }
     40             rt=ch[rt][c];
     41         }
     42         val[rt]=1;
     43     }
     44     void getfail(){
     45         while (!q.empty()) q.pop();
     46         for (int i=0;i<SZ;i++){
     47             int c=ch[0][i];
     48             if (c){ q.push(c);fail[c]=0; }
     49         }
     50         while (!q.empty()){
     51             int u=q.front();q.pop();
     52             for (int i=0;i<SZ;i++){
     53                 int c=ch[u][i];
     54                 if (!c){
     55                     ch[u][i]=ch[fail[u]][i];
     56                 }else {
     57                     int v=fail[u];
     58                     q.push(c);
     59                     fail[c]=ch[v][i];
     60                     val[c]|=val[fail[c]];
     61                 }
     62             }
     63         }
     64     }
     65     void check_print(){
     66         cout<<"****** "<<endl;
     67         for (int i=0;i<sz;i++){
     68             if (val[i]){
     69                 printf("%d %d\n",i,val[i]);
     70             }
     71         }
     72         cout<<"***** "<<endl;
     73     }
     74 }H;
     75 /////////////////建立AC自动机生产有向图/////////////
     76 typedef double Matrix[N][N];
     77 int n;
     78 Matrix A;
     79 const double eps=1e-10;
     80 int gauss(Matrix A,int n){///////////gauss消元////
     81 /*
     82         cout<<"+++++ "<<endl;
     83         for (int i=0;i<n;i++){
     84             for (int j=0;j<=n;j++){
     85                 cout<<A[i][j]<<" ";
     86             }cout<<endl;
     87         }cout<<"+++++ "<<endl;
     88 */
     89     int i,j,r,c,id;
     90     for (r=0;r<n;r++){
     91         id=r;
     92         for (i=r+1;i<n;i++)if (fabs(A[id][r])<fabs(A[i][r])) id=i;
     93         if (fabs(A[id][r])<eps) continue;
     94         if (id!=r)for (j=r;j<=n;j++) swap(A[id][j],A[r][j]);
     95 
     96         for (i=0;i<n;i++){
     97             if (i==r) continue;
     98             double tmp=A[i][r]/A[r][r];
     99             for (j=r;j<=n;j++){
    100                 A[i][j]-=tmp*A[r][j];
    101             }
    102         }
    103        /* cout<<"+++++ "<<r<<endl;
    104         for (int i=0;i<n;i++){
    105             for (int j=0;j<=n;j++){
    106                 cout<<A[i][j]<<" ";
    107             }cout<<endl;
    108         }cout<<"+++++ "<<endl;*/
    109 
    110     }
    111     for (i=0;i<n;i++) if (fabs(A[i][i])<eps && fabs(A[i][n])>eps) return 0;
    112     return 1;
    113 
    114 }
    115 void work(){
    116     memset(A,0,sizeof(A));
    117     for (int i=0;i<H.sz;i++){
    118         if (H.val[i]){
    119             A[i][i]=1;
    120             A[i][H.sz]=0;
    121         }else {
    122             for (int j=0;j<SZ;j++){
    123                 int c=H.ch[i][j];
    124                 A[i][c]+=p[j];
    125             }
    126             A[i][i]+=-1;
    127             A[i][H.sz]=-1;
    128         }
    129     }
    130     /////////////构造方程组/////////
    131     if (gauss(A,H.sz)) printf("%.6lf\n",A[0][H.sz]/A[0][0]);
    132     else printf("Infinity\n");
    133 }
    134 int main(){
    135 
    136     while (~scanf("%d",&n)){
    137         H.init();
    138         for (int i=0;i<SZ;i++) scanf("%lf",&p[i]);
    139         for (int i=0;i<n;i++){
    140             char s[20];
    141             scanf("%s",s);
    142             H.insert(s);
    143         }
    144         H.getfail();
    145         //
    146        // H.check_print();
    147         //
    148         work();
    149     }
    150     return 0;
    151 }
    152 /*
    153 2
    154 0.5000 0.5000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
    155 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
    156 cd
    157 de
    158 
    159 
    160 */
  • 相关阅读:
    Linux中将两块新硬盘合并成一个,挂载到/data目录下
    linux将硬盘格式化为xfs文件系统
    nginx配置文件
    centos 添加新硬盘,lvm对根目录扩容
    centos7重新调整分区大小
    Linux 一种调用蜂鸣器的方法
    mybatis中 keyProperty="id" 的作用
    MySQL实战45讲
    常用正则表达式最强整理(速查手册)
    linux下nacos的1.1.3版本集群部署
  • 原文地址:https://www.cnblogs.com/Rlemon/p/3022871.html
Copyright © 2011-2022 走看看