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

输入条件:先输入整数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[]={},n;
  10. int getint(char *mes){
  11. int i=;
  12. while(mes[i]!='\0' && (mes[i]<'' || mes[i]>'')) i++;
  13. return atoi(mes+i);
  14. }
  15. struct equation{
  16. double ec[];
  17. equation(){ for(int i=;i<;i++) ec[i]=; }
  18. equation operator+(const equation & S){ equation E; for(int i=;i<;i++) E.ec[i]= ec[i]+S.ec[i]; return E; }
  19. equation operator+=(const equation & S){ for(int i=;i<;i++) ec[i]+=S.ec[i]; return *this; }
  20. equation operator*(double rat){ equation E; for(int i=;i<;i++) E.ec[i]= ec[i]*rat; return E; }
  21. void print(){ for(int i=;i<n-;i++) printf("%f*%c + ",ec[i],i+'a'); printf("%f*%c = %f\n",ec[n-],n-+'a',ec[]); }
  22. };
  23. char mes[]; int idx;
  24. equation getEquation(){
  25. equation E;
  26. if(mes[idx] == '('){
  27. queue<equation> que; idx++;
  28. while(){
  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]>=''&&mes[idx]<='' || mes[idx]=='-' || mes[idx]=='+'){
  36. double t=,sign=;
  37. if(mes[idx]=='-' || mes[idx]=='+'){
  38. if(mes[idx]=='-') sign=-;
  39. idx++;
  40. }
  41. while(mes[idx]>=''&&mes[idx]<=''){
  42. t = t* + mes[idx]-'';
  43. idx++;
  44. }
  45. if(mes[idx]=='.'){
  46. double tt=0.1; idx++;
  47. while(mes[idx]>=''&&mes[idx]<=''){
  48. t += tt*(mes[idx]-'');
  49. tt *= 0.1; idx++;
  50. }
  51. }
  52. //printf("t = %f, sign = %f\n",t,sign);
  53. E.ec[]=t*sign;
  54. }else { // 'a' ---- 'z'
  55. E.ec[mes[idx]-'a']=;
  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[]=-E.ec[];
  68. E.ec[c]-=;
  69. return E;
  70. }
  71. double mat[][];
  72. int setted[],rid[];
  73. const double zero=1e-;
  74. void unset(int x){
  75. if(!setted[x]) return;
  76. setted[x]=;
  77. for(int i=x-;i>=;i--)
  78. if(fabs(mat[i][x]) > zero)
  79. unset(i);
  80. }
  81. void gauss(){
  82. memset(setted,-,sizeof(setted));
  83. for(int r=;r<n;r++){
  84. int c=r;
  85. int nonzero=-; double minv=1e99;
  86. for(int i=c;i<n;i++)
  87. if(fabs(mat[i][c]) > zero && fabs(mat[i][c]-) < minv)
  88. nonzero=i, minv=mat[i][c];
  89. if(nonzero < ) unset(r);
  90. else {
  91. double rat=/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=;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='';i<='';i++) alpha[i]=;
  106. for(int i='a';i<='z';i++) alpha[i]=;
  107. alpha['.']=; alpha['(']=; alpha[')']=;
  108. alpha['+']=; alpha['-']=;
  109. // main logic
  110. int game=;
  111. do {
  112. gets(mes); n=getint(mes);
  113. if(n <= ) break;
  114. for(int i=;i<n;i++){
  115. gets(mes); idx=;
  116. equation E = parse();
  117. //E.print();
  118. for(int j=;j<;j++)
  119. mat[i][j]=E.ec[j];
  120. }
  121. for(int j=;j<n;j++)
  122. mat[j][n]=mat[j][];
  123. printf("Game %d\n",game++);
  124. gauss();
  125. for(int j=;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();
  141. return ;
  142. }

poj1487的更多相关文章

  1. POJ1487 Single-Player Games 高斯消元

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ1487 题解概括 给出多个树形结构,由小写字母和数字表示,每个小写字母表示一棵小树.现在,以a为根节点 ...

  2. poj分类 很好很有层次感。

    初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.      ( ...

  3. 【转】POJ题目分类推荐 (很好很有层次感)

    OJ上的一些水题(可用来练手和增加自信) (poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094)初期: 一. ...

  4. 【转】ACM训练计划

    [转] POJ推荐50题以及ACM训练方案 -- : 转载自 wade_wang 最终编辑 000lzl POJ 推荐50题 第一类 动态规划(至少6题, 和 必做) 和 (可贪心) (稍难) 第二类 ...

  5. POJ 题目分类(转载)

    Log 2016-3-21 网上找的POJ分类,来源已经不清楚了.百度能百度到一大把.贴一份在博客上,鞭策自己刷题,不能偷懒!! 初期: 一.基本算法: (1)枚举. (poj1753,poj2965 ...

  6. (转)POJ题目分类

    初期:一.基本算法:     (1)枚举. (poj1753,poj2965)     (2)贪心(poj1328,poj2109,poj2586)     (3)递归和分治法.     (4)递推. ...

  7. acm常见算法及例题

    转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题  初期:一.基本算法:     (1)枚举. (poj17 ...

  8. poj分类

    初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.      ( ...

  9. 转载 ACM训练计划

    leetcode代码 利用堆栈:http://oj.leetcode.com/problems/evaluate-reverse-polish-notation/http://oj.leetcode. ...

随机推荐

  1. POJ 3678 Katu Puzzle(2 - SAT) - from lanshui_Yang

    Description Katu Puzzle is presented as a directed graph G(V, E) with each edge e(a, b) labeled by a ...

  2. jQuery下实现检测指定元素加载完毕

    检测元素出现方法.虽然是基于 jQuery 的,但是代码很简洁,可以修改成纯js版的. 文本 jQuery.fn.wait = function (func, times, interval) { v ...

  3. Activity(二)

    多个Activity之间的调用 建立一个Activity 配置layout文件夹下fragment_main.xml文件 在layout下新建other.xml文件 xml文件创建的id需要编译才能生 ...

  4. timeout Timeout时间已到.在操作完成之前超时时间已过或服务器未响应

    Timeout时间已到.在操作完成之前超时时间已过或服务器未响应 问题 在使用asp.net开发的应用程序查询数据的时候,遇到页面请求时间过长且返回"Timeout时间已到.在操作完成之间超 ...

  5. 详解 CSS 属性 - 伪类和伪元素的区别(再也不用概念盲了!!!)

    首先,阅读 w3c 对两者的定义: CSS 伪类用于向某些选择器添加特殊的效果. CSS 伪元素用于将特殊的效果添加到某些选择器. 可以明确两点,第一两者都与选择器相关,第二就是添加一些“特殊”的效果 ...

  6. 查看当前支持的MySQL字符集的命令

    查看不同的MySQL字符集有不同的方法,下面介绍的命令用于查看当前支持的MySQL字符集,希望对您学习MySQL字符集能有所帮助. mysql> show char set; +-------- ...

  7. 工厂类分离与java反射机制

    网易 博客 发现 小组 风格 手机博客 玩LOFTER,免费冲印20张照片!> 创建博客登录  加关注 黙言-在路上 奋斗 首页 日志 相册 音乐 收藏 博友 关于我             黙 ...

  8. Debug编辑通过转Release找不到命名空间

    首先查看缺少命名空间在哪个项目中 然后看缺少命名空间项目中bin/Release有没有相关文件 如果没有对该项目进行Release编译然后在编译所有项目

  9. css样式规则的简要总结

    css与文档关联起来发挥作用. css文件中是各种样式规则,由选择器和声名块构成.声明块由多条声明组成.选择器是声明要作用的对象,声明是对具体规则的描述. 声明由属性和值组成,值或是属性的错误都会使该 ...

  10. zoj1107 FatMouse and Cheese

    这是一道记忆化搜索,也就是有记录的搜索. 注意点:一次走k步不能拐弯 int bfs(int x,int y) { ; ) return ans[x][y]; ;i<;i++) { ;j< ...