poj1487

题目大意: 给一棵递归树,看链接图片,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]!='\0' && (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\n",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\n",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\n",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\n",j+'a',mes+tt);

134             }

135             */

136             printf("Expected score for %c = %.3f\n",j+'a',mat[j][n]);

137         }

138         else printf("Expected score for %c undefined\n",j+'a');

139         puts("");

140     }while(1);

141     return 0;

142 }
View Code

 

你可能感兴趣的:(poj)