题目刚开始不是很懂,读懂了又不会求期望,看了好久题解才渐渐有些明白,脑残~~
至于求期望的方法见《数论--期望》。我也是看了那个简单的求期望的公式才明白为什么E(X)=SUM{(E(X+i)+i)*p[i]}
对于在点X,下次可以走到的点为X+i,每个点走到终点的概率为P[i],由于是从X走到X+i,所以要E(x+i)+i才是变量值,p[i]为概率。然后各自相乘、
------------------------------------------------------------------------------------------------------------------
Description
题意:一个人在数轴上来回走,以pi的概率走i步i∈[1, m],给定n(数轴长度),m,e(终点),s(起点),d(方向),求从s走到e经过的点数期望
Solution
解析:设E[x]是人从x走到e经过点数的期望值,显然对于终点有:E[e] = 0
一般的:E[x] = sum((E[x+i]+i) * p[i])(i∈[1, m])
(走i步经过i个点,所以是E[x+i]+i)
建立模型:高斯消元每个变量都是一个互不相同的独立的状态,由于人站在一个点,还有一个状态是方向!例如人站在x点,有两种状态向前、向后,不能都当成一种状态建立方程,所以要把两个方向化为一个方向从而使状态不受方向的影响
实现:
n个点翻过去(除了头尾两个点~~~)变为2*(n-1)个点,例如:
6个点:012345 ---> 0123454321
那么显然,从5开始向右走其实就是相当于往回走
然后方向就由两个状态转化成一个状态的,然后每个点就是只有一种状态了,对每个点建立方程高斯消元即可
bfs判断是否可以到达终点,顺便建立方程
----------------------------------------------------------------------------------------
注意点:
1.将转移方程的右边进行分解位移,构建的方程为E[X]-SUM(E(X+i)*p[i])=SUM(P[i]*i),一共cnt个方程cnt为bfs得到的可达点,为什么会出现不可达点呢,因为当某些点的概率为0时就有可能出现不可达点。
2.注意由于方向不同,所以转移困难,但是可以利用用2倍的长度来表示,这技巧需要牢记
3.代码时借鉴kuangbin的,但是他建立的方程和求解过程不懂,所以改成自己之前写的,1a,好开心!!原来自己也有可以用自己的方法做出来的、、、
#include<stdio.h>
#include<string.h>
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define eps 1e-9
const int maxn=250;
double a[maxn][maxn],x[maxn];
int equ,var;
int num[maxn];
int cnt,m,n,N;
double p[maxn];
int Gauss() {
int i,j,k,col,max_r;
double temp;
for(k=0,col=0; k<equ&&col<var; k++,col++) {
max_r=k;
for(i=k+1; i<equ; i++) {
if(fabs(a[i][col])>fabs(a[max_r][col]))
max_r=i;
}
if(fabs(a[max_r][col])<eps) {
//说明有无穷解或无解
return 0;
}
if(k!=max_r) {
for(j=col; j<var+1; j++)
swap(a[k][j],a[max_r][j]);
}
for(i=k+1; i<equ; i++) {
if(fabs(a[i][col])>eps) {
temp=a[i][col]/a[k][col];
for(j=col; j<var+1; j++) {
a[i][j]-=a[k][j]*temp;
}
}
}
}
//有无解
for(i=k; i<equ; i++) if(fabs(a[i][var])>eps) return -1;
for(i=var-1; i>=0; i--) {
temp=a[i][var];
for(j=i+1; j<var; j++) {
if(fabs(a[i][j])>eps)
temp-=a[i][j]*x[j];
}
x[i]=temp/a[i][i];
}
return 1;
}
void bfs(int s) {
memset(num,-1,sizeof(num));
queue<int>que;
cnt=0;
num[s]=cnt++;
que.push(s);
while(!que.empty()) {
int t=que.front();
que.pop();
for(int i=1; i<=m; i++) {
if(fabs(p[i])<eps) continue;
int temp=(t+i)%n;
if(num[temp]==-1) {
num[temp]=cnt++;
que.push(temp);
}
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int s,e,d,t;
cin>>t;
while(t--) {
cin>>N>>m>>e>>s>>d;
for(int i=1; i<=m; i++) cin>>p[i],p[i]/=100;
if(e==s) {
cout<<"0.00"<<endl;
continue;
}
n=2*(N-1);
if(d==1) s=n-s;
bfs(s);
if(num[e]==-1&&num[n-e]==-1) {
cout<<"Impossible !"<<endl;
continue;
}
equ=var=cnt;
var++;
memset(a,0,sizeof(a));
memset(x,0,sizeof(x));
//构建方程矩阵
for(int i=0; i<n; i++) {
if(num[i]!=-1) {
if(i==e||i==n-e) {
a[num[i]][num[i]]=1;
x[num[i]]=0;
continue;
}
a[num[i]][num[i]]=1;
for(int j=1; j<=m; j++) {
int t=(i+j)%n;
if(num[t]!=-1) {
a[num[i]][num[t]]-=p[j];
a[num[i]][var]+=j*p[j];
}
}
}
}
int ens=Gauss();//cout<<"ens: "<<ens<<endl;
if(ens==1) printf("%.2f\n",x[num[s]]);
else cout<<"Impossible !"<<endl;
}
return 0;
}