HDU 4418 Time travel(高斯消元)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4418

题意:给出一个长度为n的序列,编号0到n-1。给出起始位置s和终止位置t,求从s到达t需要走的步数的期望。给出m,每次可以走1到m中的一步,走i步的概率为pi%(题目保证p1+p2+……+pm=100)。给出一个方向d,d=0表示开始时只能从左向右走,d=1表示开始时只能从右向左走。每次走到0或者n-1的时候都要折回去。不能到达t输出Impossible !

思路:从s开始BFS一次  可以判断是否可以到达t。设f(i)表示从i到达t的期望,设从x走下一步可以到达的位置为x1,x2,……xm,那么

f(x)=sigama((f(xi)+i)*pi),设sum=sigama(i*pi),则上式整理得:f(x1)*(-p1)+f(x2)*(-p2)+ ……+f(x)=sum,因此可建立方程组求解。

至此仍有两个问题未解决:

(1)如何解决到达两端后可以折回?比如n=6,s=2,t=4,d=0,我们将n个变成(n-1)*2=10,即0,1,2,3,4,5,6,7,8,9,x和n-x是同一个,这样从2

开始走,走到4和6其实都等于走到4;

(2)对于走不到的点应该怎么列方程呢?对于走不到的期望显然是正无穷。所以只要使等式等于INF即可。

 

double p[N],a[N][N],ans[N],sum;

int n,m;

int s,t,d,visit[N];



int sgn(double x)

{

    if(x>1e-10) return 1;

    if(x<-1e-10) return -1;

    return 0;

}



void Gauss()

{

    int i,j,k,t;

    double temp;



    for(i=0,j=0;i<n&&j<n;i++,j++)

    {

        for(k=j;k<n;k++) if(sgn(a[k][i])) break;

        for(t=0;t<=n;t++) swap(a[k][i],a[j][i]);

        for(t=0;t<n;t++) if(t!=j&&sgn(a[t][i]))

        {

            temp=a[t][i]/a[j][i];

            for(k=0;k<=n;k++) a[t][k]-=a[j][k]*temp;

        }

    }

    FOR0(i,n) ans[i]=a[i][n]/a[i][i];

    printf("%.2lf\n",ans[s]);

}



int BFS()

{

    queue<int> Q;

    Q.push(s); clr(visit,0); visit[s]=1;

    int i,u,v;

    while(!Q.empty())

    {

        u=Q.front();

        Q.pop();

        for(i=1;i<=m;i++)

        {

            v=(u+i)%n;

            if(sgn(p[i])&&!visit[v]) visit[v]=1,Q.push(v);

        }

    }

    return visit[t]||visit[(n-t)%n];

}



void build()

{

    clr(a,0);

    int i,j;

    FOR0(i,n)

    {

        a[i][i]=1;

        if(!visit[i]) a[i][n]=dinf;

        if(i==t||i==(n-t)%n) a[i][n]=0;

        else

        {

            a[i][n]=sum;

            for(j=1;j<=m;j++) a[i][(i+j)%n]-=p[j];

        }

    }

}



int main()

{

    rush()

    {

        RD(n,m); RD(t,s); RD(d);

        int i;

        sum=0;

        FOR1(i,m) RD(p[i]),p[i]/=100,sum+=p[i]*i;

        n=(n-1)<<1;

        if(d==1) s=(n-s)%n;

        if(s==t) puts("0.00");

        else if(!BFS()) puts("Impossible !");

        else build(),Gauss();

    }

    return 0;

}

 

  

 

你可能感兴趣的:(time)