zoukankan      html  css  js  c++  java
  • poj1487

    题目大意: 给一棵递归树,看链接图片,从根节点开始对于每个节点往它的子节点移动,直到叶子节点停止。每个节点选哪一个孩子节点继续往下走是随机的(等概率)。然后叶子节点都会标记一个数值,记为走到该节点的得分。

    输入条件:先输入整数n(n=0时结束),接下来有n行(n <= 26),每一行会为前n个小写字母(每个字母作为一个变量)的描述。如a = (1 b)表示 f(a) = 1/2 * (1 + f(b))其中f(x)为x节点的得分期望。

    现在对n个小写字母表示的变量节点,求出那个节点的得分期望即f(x) (x=a,b,c ...)。

    这个题相当有意思,有意思在于它的输入——基于某个字符集的语义分析。递归向下分析的策略,而且是非常典型LL(1)文法!

    S -> XWEWT

    X -> (X)|a|b|c|...|z

    E -> '='

    W -> {Blank}|空

    T -> (U)

    U -> T|X|I

    U -> UwU

    w ->  {Blank}

    I -> [+|-]{Digit}+[.{Digit}]

    这道题另外一个关键点是将T转化成方程式,然后综合这n个方程式,使用gauss消元求解。

    gauss消元其实就是线性代数中,化简行列式然后进行求解。不会的亲们回去好好看看线性代数的书,不要看网上某些人写的不清不楚的报告。

    只是有一点需要注意:计算机中的数字是有界的,要时刻注意数字边界问题!

    还有,很多事情需要自己亲身实践,我贡献了很多次WA,一个大原因是听人家要排除输出"-0.000"的问题。

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <queue>
      5 #include <algorithm>
      6 #include <cstdlib>
      7 #include <cmath>
      8 using namespace std;
      9 int alpha[128]={0},n;
     10 int getint(char *mes){
     11     int i=0;
     12     while(mes[i]!='' && (mes[i]<'0' || mes[i]>'9')) i++;
     13     return atoi(mes+i);
     14 }
     15 struct equation{
     16     double ec[27];
     17     equation(){ for(int i=0;i<27;i++) ec[i]=0; }
     18     equation operator+(const equation & S){ equation E; for(int i=0;i<27;i++) E.ec[i]= ec[i]+S.ec[i];  return E; }
     19     equation operator+=(const equation & S){ for(int i=0;i<27;i++) ec[i]+=S.ec[i];  return *this; }
     20     equation operator*(double rat){ equation E; for(int i=0;i<27;i++) E.ec[i]= ec[i]*rat;  return E; }
     21     void print(){ for(int i=0;i<n-1;i++) printf("%f*%c + ",ec[i],i+'a'); printf("%f*%c = %f
    ",ec[n-1],n-1+'a',ec[26]); }
     22 };
     23 char mes[1010000]; int idx;
     24 equation getEquation(){
     25     equation E;
     26     if(mes[idx] == '('){
     27         queue<equation> que; idx++;
     28         while(1){
     29             while(!alpha[mes[idx]]) idx++; //跳到下一个合法字母
     30             if(mes[idx]==')') break;
     31             que.push(getEquation());
     32         } idx++;
     33         double quesize=1.0/que.size();
     34         while(!que.empty()) E += que.front()*quesize, que.pop();
     35     }else if(mes[idx]>='0'&&mes[idx]<='9' || mes[idx]=='-' || mes[idx]=='+'){
     36         double t=0,sign=1;
     37         if(mes[idx]=='-' || mes[idx]=='+'){
     38             if(mes[idx]=='-') sign=-1;
     39             idx++;
     40         }
     41         while(mes[idx]>='0'&&mes[idx]<='9'){
     42             t = t*10 + mes[idx]-'0';
     43             idx++;
     44         }
     45         if(mes[idx]=='.'){
     46             double tt=0.1; idx++;
     47             while(mes[idx]>='0'&&mes[idx]<='9'){
     48                 t += tt*(mes[idx]-'0');
     49                 tt *= 0.1; idx++;
     50             }
     51         }
     52         //printf("t = %f, sign = %f
    ",t,sign);
     53         E.ec[26]=t*sign;
     54     }else { // 'a' ---- 'z'
     55         E.ec[mes[idx]-'a']=1;
     56         idx++;
     57     }
     58     while(!alpha[mes[idx]]) idx++; //跳到下一个合法字母
     59     return E;
     60 }
     61 equation parse(){
     62     while(mes[idx]<'a' || mes[idx]>'z') idx++;
     63     int c=mes[idx]-'a';
     64     while(mes[idx]!='=') idx++; idx++;
     65     while(!alpha[mes[idx]]) idx++; //跳到下一个合法字母
     66     equation E = getEquation();
     67     E.ec[26]=-E.ec[26];
     68     E.ec[c]-=1;
     69     return E;
     70 }
     71 double mat[26][27];
     72 int setted[26],rid[26];
     73 const double zero=1e-10;
     74 void unset(int x){
     75     if(!setted[x]) return;
     76     setted[x]=0;
     77     for(int i=x-1;i>=0;i--)
     78     if(fabs(mat[i][x]) > zero)
     79         unset(i);
     80 }
     81 void gauss(){
     82     memset(setted,-1,sizeof(setted));
     83     for(int r=0;r<n;r++){
     84         int c=r;
     85         int nonzero=-1; double minv=1e99;
     86         for(int i=c;i<n;i++)
     87         if(fabs(mat[i][c]) > zero && fabs(mat[i][c]-1) < minv)
     88             nonzero=i, minv=mat[i][c];
     89         if(nonzero < 0) unset(r);
     90         else {
     91             double rat=1/mat[nonzero][c];
     92             for(int i=c;i<=n;i++) mat[nonzero][i] *= rat, swap(mat[nonzero][i],mat[r][i]);
     93             for(int i=0;i<n;i++)
     94             if(i!=r && fabs(mat[i][c]) > zero){
     95                 rat = mat[i][c];
     96                 for(int j=c;j<=n;j++)
     97                     mat[i][j] -= rat*mat[r][j];
     98             }
     99         }
    100     }
    101 }
    102 int main()
    103 {
    104 // init the legal alpha
    105     for(int i='0';i<='9';i++) alpha[i]=1;
    106     for(int i='a';i<='z';i++) alpha[i]=1;
    107     alpha['.']=1; alpha['(']=1; alpha[')']=1;
    108     alpha['+']=1; alpha['-']=1;
    109 // main logic
    110     int game=1;
    111     do {
    112         gets(mes); n=getint(mes);
    113         if(n <= 0) break;
    114         for(int i=0;i<n;i++){
    115             gets(mes); idx=0;
    116             equation E = parse();
    117             //E.print();
    118             for(int j=0;j<27;j++)
    119                 mat[i][j]=E.ec[j];
    120         }
    121         for(int j=0;j<n;j++)
    122              mat[j][n]=mat[j][26];
    123         printf("Game %d
    ",game++);
    124         gauss();
    125         for(int j=0;j<n;j++)
    126         if(setted[j]) {
    127             /* 排除输出 -0.000 的问题, 这里多余了
    128             int tt=0;
    129             for(int i=0;i<n;i++){
    130                 sprintf(mes,"%.3f",mat[j][n]);
    131                 tt=0;
    132                 if(memcmp("-0.000",mes,5)==0) tt=1;
    133                 printf("Expected score for %c = %s
    ",j+'a',mes+tt);
    134             }
    135             */
    136             printf("Expected score for %c = %.3f
    ",j+'a',mat[j][n]);
    137         }
    138         else printf("Expected score for %c undefined
    ",j+'a');
    139         puts("");
    140     }while(1);
    141     return 0;
    142 }
    View Code
  • 相关阅读:
    Java标签实现分页
    Servlet过滤器介绍之原理分析
    java超强分页标签演示
    Mybatis中resultMap与resultType区别
    洛谷 P1002 过河卒
    洛谷 P2181 对角线
    ACM常数优化
    2020 年百度之星&#183;程序设计大赛
    AtCoder Beginner Contest 171 E
    AtCoder Beginner Contest 171 D
  • 原文地址:https://www.cnblogs.com/karlvin/p/3422292.html
Copyright © 2011-2022 走看看