Single-Player Games
题解
第二位贞难调诞生了
其实大体的思路挺好想的,主要是写着字符串处理与高斯消元比较麻烦。
根据每一个数我们是很容易得到一个方程,毕竟它给我们的就是一个方程
我们很容易发现一个括号内的期望值,就是它可以走的儿子的期望值的平均数,我们可以先将后面那一大堆括号化简,得到一个方程,形如的方程式,我们先将左边的移动过去,再将右边表示常数的移动过来,就得到了一个典型的高斯消元的方程式,我们总共有个这样的方程式,解出来即可。
说一些需要注意的点吧
- 方程式中的常数读入时可能为负数
- 总共的值加起来可能爆int
- 无论是无解还是自由元都要输出undefined
- 如果一个自由元可以被解出来必须要将其给解出来
- 因为卡精度可能输出-0.000
反正笔者调了好久才过
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
typedef long long LL;
const double eps=1e-9;
int n,m,name[30],tot;
double arr[30][30],ans[30];
bool frecnt[30];
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
void swap1(int x,int y,int len){for(int i=1;i<=len;i++)swap(arr[x][i],arr[y][i]);}
int gauss(){
int t=1,p=1;
/*for(int i=1;i<=m;i++){
for(int j=1;j<=n+1;j++)
printf("%d ",arr[i][j]);
puts("");
}*/
for(;p<=m&&t<=m;p++,t++){
int maxx=p;
for(int j=p;j<=m;j++)
if(Fabs(arr[j][t])>Fabs(arr[maxx][t]))
maxx=j;
if(p!=maxx)swap1(p,maxx,n+1);
if(Fabs(arr[p][t])<eps){p--;continue;}
for(int j=p+1;j<=m;j++){
if(Fabs(arr[j][t])<eps)continue;
double tmp=arr[j][t]/arr[p][t];
for(int k=t;k<=n+1;k++)
arr[j][k]-=arr[p][k]*tmp;
}
}
for(int i=p;i<=m;i++)if(Fabs(arr[i][t])>eps)return -1;
if(p<=m){
int num=0,freidx;
for(int i=p-1;i>0;i--){
num=0;double tmp=arr[i][n+1];
for(int j=1;j<=n;j++)
if(Fabs(arr[i][j])>eps&&frecnt[j])
num++,freidx=j;
if(num>1)continue;tmp=arr[i][n+1];
for(int j=1;j<=n;j++)
if(Fabs(arr[i][j])>eps&&j!=freidx)
tmp-=arr[i][j]*ans[j];
ans[freidx]=tmp/arr[i][freidx];frecnt[freidx]=0;
}
return m-p+1;
}
for(int i=m;i>0;i--){
double tmp=arr[i][n+1];
for(int j=i+1;j<=n;j++)
tmp-=arr[i][j]*ans[j];
ans[i]=tmp/arr[i][i];
}
return 0;
}
double sum[200],sa[200][30];
int cnt[200],num;
char ch[250];
signed main(){
while(scanf("%d",&n)!=EOF&&n){
memset(arr,0,sizeof(arr));getchar();
memset(name,0,sizeof(name));
memset(ans,0,sizeof(ans));
memset(frecnt,1,sizeof(frecnt));
for(int i=1;i<=n;i++){
memset(sum,0,sizeof(sum));
memset(sa,0,sizeof(sa));
memset(cnt,0,sizeof(cnt));
gets(ch);name[i]=ch[0]-'a'+1;
bool flag=false;num=0;
int id=1,len=(int)strlen(ch);
while(id<len){
//printf("%d:%c %d\n",++siz,ch,num);
bool af=false;;
if(ch[id]=='(')cnt[num]++,num++,id++,flag=af=1;
if(ch[id]==')'){
double tmp=sum[num]/(1.0*cnt[num]);
for(int i=1;i<=n;i++){
sa[num-1][i]+=sa[num][i]/(1.0*cnt[num]);
sa[num][i]=0;
}
cnt[num]=sum[num]=0;af=1;
num--;sum[num]+=tmp;id++;
}
if(('0'<=ch[id]&&ch[id]<='9')||ch[id]=='-'){
LL x=0,f=1;af=1;
while(('0'<=ch[id]&&ch[id]<='9')||ch[id]=='-'){
if(ch[id]=='-')f=-1;
else x=x*10ll+(ch[id]-'0');
id++;if(id>=len)break;
}
x*=f;cnt[num]++;sum[num]+=x;
}
if('a'<=ch[id]&&ch[id]<='z'){
int nam=ch[id]-'a'+1;sa[num][nam]++;
cnt[num]++;id++;af=1;
}
if(!af)id++;
}
sa[0][name[i]]--;
for(int j=1;j<=n;j++)arr[i][j]=sa[0][j],sa[0][j]=0;
arr[i][n+1]=-sum[0];
}
m=n;int ak=gauss();printf("Game %d\n",++tot);
for(int i=1;i<=n;i++){
if(Fabs(ans[i])<eps)ans[i]=0;
if(ak==-1||(ak>0&&frecnt[i]))
printf("Expected score for %c undefined\n",name[i]+'a'-1);
else printf("Expected score for %c = %.3f\n",name[i]+'a'-1,ans[name[i]]);
}
puts("");
}
return 0;
}