欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - POJ1487


题解概括

   给出多个树形结构,由小写字母和数字表示,每个小写字母表示一棵小树。现在,以a为根节点,构建一棵大树,树可能是无限的。现在,一个人从树根往叶子走,直到无法走为止,得到该叶子结点上数值所表示的相应分数,人在分叉的地方走每条路的概率是一样的,求得分期望。


题解

  首先通过关系建立方程组。

  这个貌似很麻烦,但是很暴力,有码量没有难度。

  然后高斯消元解方程。

  要注意精度的问题。

  解的时候要标记自由元。

  也有点麻烦。

  具体的看代码吧。


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long double LD;
const LD Eps=1e-8;
const int N=30;
int n,Case=0,now,pos[N];
char str[300];
bool free_x[N];
LD a[N][N],x[N];
void GetLn(){
while (getchar()!='\n');
}
int Match_Pracket(int now){//now为当前要匹配的左括号位置。
int len=strlen(str+1),p=0;
for (int i=now;i<=len;i++){
if (str[i]=='(')
p++;
if (str[i]==')')
p--;
if (!p)
return i;
}
return -1;
}
bool Is_Num_Part(char ch){
return ch=='-'||('0'<=ch&&ch<='9');
}
int GetNum(int now,int &Next){//now为当前要计算的数字的最左位置,Next返回跳过数字后的位置。
int len=strlen(str+1),f=1,x=0;
if (str[now]=='-')
f=-1;
else
x=str[now]-'0';
while (Is_Num_Part(str[++now]))
x=x*10+str[now]-'0';
Next=now;
return x*f;
}
void dfs(int L,int R,LD p){
if (L>R)
return;
int tot=0,i;
for (i=L;i<=R;){
if (Is_Num_Part(str[i])){
int j,v=GetNum(i,j);
i=j,tot++;
continue;
}
if (str[i]=='('){
i=Match_Pracket(i)+1;
tot++;
continue;
}
if ('a'<=str[i]&&str[i]<='z'){
i++,tot++;
continue;
}
i++;
}
p=p/tot;
for (int i=L;i<=R;){
if (Is_Num_Part(str[i])){
int j,v=GetNum(i,j);
i=j,a[now][n]-=p*v;
continue;
}
if (str[i]=='('){
int j=Match_Pracket(i);
dfs(i+1,j-1,p);
i=j+1;
continue;
}
if ('a'<=str[i]&&str[i]<='z')
a[now][str[i]-'a']+=p;
i++;
}
}
int Gauss(){
memset(free_x,0,sizeof free_x);
memset(pos,0,sizeof pos);
int k,c;
for (k=c=0;k<n&&c<n;k++,c++){
int Mk=k;
for (int i=k+1;i<n;i++)
if (fabs(a[Mk][c])<fabs(a[i][c]))
Mk=i;
if (Mk!=k)
for (int i=c;i<=n;i++)
swap(a[Mk][i],a[k][i]);
if (fabs(a[k][c])<Eps){
k--;
free_x[c]=1;
continue;
}
pos[k]=c;
for (int i=k+1;i<n;i++)
if (fabs(a[i][c])>Eps){
for (int j=n;j>=c;j--)
a[i][j]=a[i][j]-a[k][j]/a[k][c]*a[i][c];
a[i][c]=0;
}
}
for (int i=k;i<n;i++)
if (fabs(a[i][n])>Eps)
return -1;
memset(x,0,sizeof x);
for (int i=k-1;i>=0;i--){
if (free_x[pos[i]])
continue;
LD tmp=a[i][n];
for (int j=pos[i]+1;j<n;j++){
if (fabs(a[i][j])<Eps)
continue;
if (free_x[j]){
free_x[pos[i]]=1;
break;
}
tmp-=a[i][j]*x[j];
}
if (!free_x[pos[i]])
x[pos[i]]=tmp/a[i][pos[i]];
if (fabs(x[pos[i]])<Eps)
x[pos[i]]=0;
}
return 0;
}
int main(){
while (~scanf("%d",&n)&&n){
GetLn();
memset(a,0,sizeof a);
for (now=0;now<n;now++){
a[now][now]-=1;
gets(str+1);
int pos=1;
while (str[pos]!='=')
pos++;
dfs(pos+1,strlen(str+1),1);
}
int ans=Gauss();
printf("Game %d\n",++Case);
for (int i=0;i<n;i++)
if (free_x[i])
printf("Expected score for %c undefined\n",i+'a');
else
printf("Expected score for %c = %.3Lf\n",i+'a',x[i]);
puts("");
}
return 0;
}

  

POJ1487 Single-Player Games 高斯消元的更多相关文章

  1. 【CF446D】DZY Loves Games 高斯消元+矩阵乘法

    [CF446D]DZY Loves Games 题意:一张n个点m条边的无向图,其中某些点是黑点,1号点一定不是黑点,n号点一定是黑点.问从1开始走,每次随机选择一个相邻的点走过去,经过恰好k个黑点到 ...

  2. POJ 1487:Single-Player Games 浮点数高斯消元

    Single-Player Games Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1287   Accepted: 36 ...

  3. 单(single):换根dp,表达式分析,高斯消元

    虽说这题看大家都改得好快啊,但是为什么我感觉这题挺难.(我好菜啊) 所以不管怎么说那群切掉这题的大佬是不会看这篇博客的所以我要开始自嗨了. 这题,明显是树dp啊.只不过出题人想看你发疯,询问二合一了而 ...

  4. Codeforces 446D - DZY Loves Games(高斯消元+期望 DP+矩阵快速幂)

    Codeforces 题目传送门 & 洛谷题目传送门 神仙题,%%% 首先考虑所有格子都是陷阱格的情况,那显然就是一个矩阵快速幂,具体来说,设 \(f_{i,j}\) 表示走了 \(i\) 步 ...

  5. HDU5088——Revenge of Nim II(高斯消元&矩阵的秩)(BestCoder Round #16)

    Revenge of Nim II Problem DescriptionNim is a mathematical game of strategy in which two players tak ...

  6. hdu 5833 Zhu and 772002 高斯消元

    Zhu and 772002 Problem Description Zhu and 772002 are both good at math. One day, Zhu wants to test ...

  7. SGU 275 To xor or not to xor 高斯消元求N个数中选择任意数XORmax

    275. To xor or not to xor   The sequence of non-negative integers A1, A2, ..., AN is given. You are ...

  8. POJ 1681---Painter's Problem(高斯消元)

    POJ   1681---Painter's Problem(高斯消元) Description There is a square wall which is made of n*n small s ...

  9. HDU4870_Rating_双号从零单排_高斯消元求期望

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4870 原题: Rating Time Limit: 10000/5000 MS (Java/Other ...

随机推荐

  1. Java图片比对

    在自动化测试中,除了普通的值验证,经常还有一些图片验证,比如图片的匹配率,输出图片的差异图片等.本文主要用到了BufferedImage类来操作图片比对和输出差异图片,大体的思路如下: 1. 通过Im ...

  2. VS中修改工程名的解决方案

    VS中修改工程名的解决方案: 一.先修改工程名/解决方案名(在VS中修改即可)举例,原先的工程名为OldProject   想要改成NewProject1.找到工程/解决方案所在的文件夹(已工程名/解 ...

  3. Mongodb 副本集

    mongodb主从模式就是一个 单副本的应用:没有很好的扩展性和容错性: 副本集的多个副本保证了容错性:主服务器负责整个副本集的读写,副本集定时同步数据:主节点挂掉:副本集会自动选举一个主的服务器: ...

  4. QDialog对话框

    QDialog对话框,用来实现那些只是暂时存在的用户界面,是独立的窗口,但通常也有父窗口对话框有模态和非模态两种,,非模态对话框的行为和使用方法都类似于普通的窗口,模态对话框则有所不同,当模态对话框显 ...

  5. spfa算法----最短路

    题目链接:https://cn.vjudge.net/contest/66569#problem/A 代码: vis数组代表是否还有用,首先初始化为0,首先第一个点入队列,标记为1,然后刚入队列的时候 ...

  6. 2018-2019-2 网络对抗技术 20165227 Exp1 PC平台逆向破解

    2018-2019-2 网络对抗技术 20165227 Exp1 PC平台逆向破解 实验内容及步骤 实验一:直接修改程序机器指令,改变程序执行流程 知识要求:Call指令,EIP寄存器,指令跳转的偏移 ...

  7. android view绘制流程 面试

    一.view树的绘制流程 measure--->layout--->draw measure 1.ViewGroup.LayoutParams 指定部件的长宽 2.MeasureSpec ...

  8. 2017/05/03 java 基础 随笔

    1.硬盘500G 厂商是按照1000计算的 500g=500*1000*1000/1024/1024=465g 2.jdk1.7可以表示二进制了 0b001(b大小写无所谓) 3.进制转换 4.原码, ...

  9. python 历险记(一)— python 的String,集合(List,元组,Dict)

    目录 引言 String 有哪些有用的方法? 如何拼接字符串? 如何分隔字符串? 如何获取字符串长度 如何将 list 拼接成字符串? 如何替换字符串? 如何去除字符串中的空格? 如何子字符串是否包含 ...

  10. 每天一个linux命令【转】

    转自:http://www.cnblogs.com/peida/archive/2012/12/05/2803591.html 开始详细系统的学习linux常用命令,坚持每天一个命令,所以这个系列为每 ...