您的位置:首页 > 其它

poj 1487 Single-Player Games(高斯消元+字符串处理)

2016-11-28 21:38 501 查看
题意:

给你几棵树,每棵树的叶子节点都有一个值,这个值可能是直接给出,也可能是其它树的期望值,问每棵树走到叶子节点获得的值的期望是多少。

每棵树的编号是从a到a+n-1.

思路:

被这道题,卡了好几天,快卡哭了QAQ。

首先麻烦的是字符串的处理,用递归是一种比较好的办法,先记录下同一个括号里所存在的元素个数,再往下递归就好。

然后建立方程。记a树的期望为Ea,把有确定值的叶子节点的期望求出来加和为va,以及求出走到存放其它树(str)的期望的叶子节点的概率记为a[str-'a'],

则可列出方程:   Ea=Ea*a['a'-'a']+Eb*a['b'-'a']+Ec*a['c'-'a']……+va;

                          移项得:va=(1-Ea)*a['a'-'a']-Eb*a['b'-'a']-Ec*a['c'-'a']......(我的程序不这样移就会wa,不知道为什么)

然后每棵树都可以列出这样的一个方程,套用下高消消元浮点型解模板。

但是这个题还需要注意一个情况,当出现有自由变元的时候,并不是就有多解,对于一些只包含一个自由变元的方程组,是可以求解的,我们就要求出这些方程组中那个唯一的自由变元的解,而对于其它不能确定的变元,输出undefined即可。

这题真恶心!

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn=1e2;
const double eps=1e-8;
int n;
char str[maxn+5];
double a[maxn+5][maxn+5];
double b[maxn+5];
double kh[maxn+5];
bool v[maxn+5];
bool freex[maxn+5]; //记录是否为自由变元
struct eee
{
int s;
double p;
int valu;
int zt;
} que[maxn+5];
void gauss(int n)
{
int i, j, row, col, equ=n, var=n;
for(row=0, col=0; row<equ && col<var; row++, col++)
{
int maxr=row;
for(i=row; i<equ; i++)
{
if(fabs(a[i][col])>fabs(a[maxr][col]))
{
maxr=i;
}
}
if(fabs(a[maxr][col])<eps)
{
row--;
continue;
}
for(j=col; j<var+1; j++)
{
swap(a[maxr][j], a[row][j]);
}
for(i=row+1; i<equ; i++)
{
if(fabs(a[i][col])>eps)
{
double s=a[i][col]/a[row][col];
for(j=col; j<var+1; j++)
{
a[i][j]-=a[row][j]*s;
}
}
}
}
if(row < n)
{
for(i=row-1; i>=0; i--)
{
int num=0, id;
for(j=i; j<n; j++) //找出该方程中有几个自由变元
{
if(freex[j] && fabs(a[i][j])>eps)
{
num++;
id=j;  //当出现只有一个自由变元时,就是id了
}
}
if(num>1)continue; // 有多个自由变元,该方程无解
double tmp=a[i]
;
for(j=id+1; j<n; j++)
{
tmp-=a[i][j]*b[j];
}
b[id]=tmp/a[i][id];
freex[id]=0; //已求出该变元的值,将其标记为非自由变元。
}
for(i=0; i<n; i++)
{
printf("Expected score for %c ", i+'a');
if(!freex[i])printf("= %.3lf\n", b[i]);
else printf("undefined\n");
}
//        printf("\n");
return;
}
for(i=equ-1; i>=0; i--)
{
double tmp=a[i][var];
for(j=i+1; j<var; j++)
{
tmp-=a[i][j]*b[j];
}
//        printf("%.3lf %d %.3lf\n", a[i][i], i, tmp);
b[i]=tmp/a[i][i];

}
for(i=0; i<n; i++)
{
printf("Expected score for %c = %.3lf\n", i+'a', b[i]);
}

}

void find(int x, double p, int s, int d)
{
int i, j;
int num=0;// kuohao number
double enumber=0.0; // element number
for(i=s+1; i<d; i++)
{
if(str[i]=='(')
{
num++;
}
else if(str[i]==')')
{
num--;
if(num==0)
{
enumber+=1;
}
}
else if(str[i]!=' ' && num==0)
{
while(str[i+1]>='0' && str[i+1]<='9')i++;

enumber+=1;
}
}
num=0;
int st=0;
for(i=s+1; i<d; i++)
{
if(str[i]=='(')
{
if(num==0) st=i;
num++;

}
else if(str[i]==')')
{
num--;
if(num==0)
{

find(x, p*1.0/enumber, st, i);
}
}
else if(str[i]>='a' && str[i]<='z' && num==0)
{
a[x][str[i]-'a']-=p*1.0/enumber;
}
else if(str[i]=='-' && num==0)
{
int ans=0;
i++;
while(str[i]>='0' && str[i]<='9')
{
ans=ans*10+str[i]-'0';

i++;
}
ans=-ans;
a[x]
+=1.0*ans*p/enumber;
}
else if(str[i]<='9' && str[i]>='0' && num==0)
{
int ans=0;
while(str[i]<='9' && str[i]>='0')
{
ans=ans*10+str[i]-'0';
i++;
}

//            printf("%lf %.0lf\n", ans*p/enumber, ans);
a[x]
+=1.0*ans*p/enumber;
}
}
return;
}

int main()
{
int isfirst=1;
int e=1;
while(~scanf("%d", &n))
{
if(n==0)break;

int i, j;
memset(v, 0, sizeof(v));
memset(a, 0, sizeof(a));
memset(freex, true, sizeof(freex)); //先将所有变量默认为自由变元,之后会在求解过程中求出哪些变元不是自由变元。
getchar();
for(i=0; i<n; i++)
{

gets(str);
//            printf("%s\n", str);
double var=0;
double p=1.0;
a[i][i]=1;
int st=0, ed=0, len=strlen(str);
for(j=0; str[j]; j++)
{
if(str[j]=='(')
{
st=j;break;
}
}
for(j=len-1; j>=0; j--)if(str[j]==')'){ed=j;break;}
find(i, p, st, ed);
}

if(isfirst)isfirst=0;
else printf("\n");
printf("Game %d\n", e++);
gauss(n);

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: