hdu4418 Time travel 【期望+dp】

来源:互联网 发布:mac口红一盒 编辑:程序博客网 时间:2024/05/22 17:02

题目刚开始不是很懂,读懂了又不会求期望,看了好久题解才渐渐有些明白,脑残~~

至于求期望的方法见《数论--期望》。我也是看了那个简单的求期望的公式才明白为什么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-9const 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_JUDGEfreopen("in.txt","r",stdin);#endifint 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;}



0 0