zoukankan      html  css  js  c++  java
  • XCOJ 1168 (搜索+期望+高斯消元法)

    题目链接http://xcacm.hfut.edu.cn/oj/problem.php?id=1168

    题目大意:D是起点,E是终点。每次等概率往某个方向走,问到达终点的期望步数。到不了终点或步数超限输出tragedy!

    解题思路

    如果某个点四周都不是障碍,不难有方程:

    E(X,Y)= (1/4)E(X-1,Y)+ (1/4)E(X+1,Y)+ (1/4)E(X,Y-1)+ (1/4)E(X,Y+1)+1

    变形为一般式,且系数化1:4*E(X,Y)-E(X-1,Y)- E(X+1,Y) - E(X,Y-1) - E(X,Y+1) = 4

    更一般化,如果周围有cnt个点可去: cnt*E(X,Y)-E(X-1,Y)- E(X+1,Y) - E(X,Y-1) - E(X,Y+1) = cnt

    对于不可达点(不一定是障碍)或终点:E(X,Y)= 0,这一步的处理很重要,不然会导致出现自由变元,导致无穷解。

    那么本题思路很明显了:

    ①BFS或是DFS,标记各点的可达情况。

    ②对于每个点(元),首先看其是否为不可达点或是终点,令其系数为1后continue

      如果不是,枚举四个方向,系数设为-1。最后该点系数为cnt,解向量初始化为cnt。

    ③高斯消元(本模板是高斯—约当消元法)。

    ④由于方程是把起点和终点逆过来列方程的,所以元[起点]的解才是最后的ans。(类似记忆化搜索的方式)

     

    #include "cstdio"
    #include "queue"
    #include "cstring"
    #include "algorithm"
    #include "math.h"
    using namespace std;
    #define eps 1e-15
    char map[15][15],s[15];
    int n,m,T,sx,sy,ex,ey,vis[15][15],dir[4][2]={-1,0,1,0,0,-1,0,1},equ;
    double ratio[105][105];
    struct status
    {
        int x,y;
        status(int x,int y):x(x),y(y) {}
    };
    void Bfs(int x,int y)
    {
        queue<status> Q;Q.push(status(x,y));
        vis[x][y]=1;
        while(!Q.empty())
        {
            status t=Q.front();Q.pop();
            for(int s=0;s<4;s++)
            {
                int X=t.x+dir[s][0],Y=t.y+dir[s][1];
                if(X<0||Y<0||X>=n||Y>=m||vis[X][Y]||map[X][Y]=='X') continue;
                vis[X][Y]=1;
                Q.push(status(X,Y));
            }
        }
    }
    void Reset()
    {
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
        {
            if((i==ex&&j==ey)||!vis[i][j]) {ratio[i*m+j][i*m+j]=1;continue;}
            int cnt=0;
            for(int s=0;s<4;s++)
            {
                int x=i+dir[s][0],y=j+dir[s][1];
                if(x>=0&&y>=0&&x<n&&y<m&&map[x][y]=='.')
                {
                    ratio[i*m+j][x*m+y]=-1;
                    cnt++;
                }
            }
            ratio[i*m+j][equ]=ratio[i*m+j][i*m+j]=cnt;
        }
    }
    bool Gauss()
    {
        for(int i=0;i<equ;i++)
        {
            int k=i;
            for(int j=i;j<equ;j++)
                if(fabs(ratio[j][i])>fabs(ratio[k][i])) k=j;
            swap(ratio[k],ratio[i]);
            if(fabs(ratio[i][i])<eps) return false;
            for(int j=i+1;j<=equ;j++) ratio[i][j]/=ratio[i][i];
            for(int j=0;j<equ;j++)
                if(i!=j)
                    for(int k=i+1;k<=equ;k++) ratio[j][k]-=ratio[j][i]*ratio[i][k];
        }
        return true;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            equ=n*m;
            for(int i=0;i<n;i++)
            {
                scanf("%s",&s);
                for(int j=0;j<strlen(s);j++)
                {
                    map[i][j]=s[j];
                    if(s[j]=='D') {map[i][j]='.';sx=i;sy=j;}
                    if(s[j]=='E') {map[i][j]='.';ex=i;ey=j;}
                }
            }
            Bfs(sx,sy);
            Reset();
            bool ok=Gauss();
            if(ok&&ratio[sx*n+sy][equ]<=1000000) printf("%.2lf
    ",ratio[sx*n+sy][equ]);
            else printf("tragedy!
    ");
            memset(ratio,0,sizeof(ratio));
            memset(vis,0,sizeof(vis));
        }
    }
    2709 2013217098 Accepted
    1148
    88
    C++ 2668 B 2014-11-06 20:51:07

     

     

     

  • 相关阅读:
    ASP.NET中Session,Application,Viewstate,Cache,隐藏域和带参数的传接收值的用法
    JS页面跳转搜集
    SQL中常用的日期转化
    DIV+CSS兼容性解决IE6/IE7/FF浏览器的通用方法
    C#中将数据导出为EXCEL方式汇总
    正则表达式大全
    ASP.NET中Cookie用法小节
    div+CSS浏览器兼容问题整理
    站长常用的200个js代码
    [转]主机和终端
  • 原文地址:https://www.cnblogs.com/neopenx/p/4079962.html
Copyright © 2011-2022 走看看