高斯消元求期望 Random Walk (浮点数Gauss模板 挑战P288)

本文介绍如何利用高斯消元方法解决 ACM 中的数论问题,特别是针对挑战 P288 中的浮点数处理,探讨在求解随机行走期望问题上的应用。
摘要由CSDN通过智能技术生成
从(0,0)出发,可上下左右移动,不能移动到#处。
求第一次到达(N-1,M-1)格子的期望步数。数据至少有1条能从(0,0)到达(N-1,M-1)的路径。


3 10
.#...#...#
.#.#.#.#.#
...#...#..


10 10
..........
..........
..........
..........
..........
..........
..........
..........
..........
..........


输出:
361.00000000

542.10052168





#include<vector>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<cstdio>
#include<cstring>
#define sf(n)    scanf("%d", &n)
#define sff(a,b) scanf("%d %d", &a, &b)
#define MT(x,i)  memset(x,i,sizeof(x))
typedef long long LL;
using namespace std;
const double eps=1e-9;
const int MAXN=16;
double A[MAXN*MAXN][MAXN*MAXN],b[MAXN*MAXN];//方程的左边的矩阵和等式右边的值,求解之后x存的就是结果
//点与点的关系,一定是方阵  //值数组,高斯消元求Ax=b;
//返回0表示无解,1表示有解
int Gauss(int equ,int var)//int equ,var;方程数和未知数个数//行数,列数
{
    int i,j,k,col,max_r;
    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; j++)
                swap(A[k][j],A[max_r][j]);
            swap(b[k],b[max_r]);
        }
        b[k]/=A[k][col];
        for(j=col+1; j<var; j++)A[k][j]/=A[k][col];
        A[k][col]=1;
        for(i=0; i<equ; i++)
            if(i!=k)
            {
                b[i]-=b[k]*A[i][k];
                for(j=col+1; j<var; j++)A[i][j]-=A[k][j]*A[i][col];
                A[i][col]=0;
            }
    }
    return 1;
}

int dx[4]={-1,1, 0,0};
int dy[4]={ 0,0,-1,1};
int N,M;
char grid[MAXN][MAXN];//地图
bool can_goal[MAXN][MAXN];//为true则能到达终点
bool judge(int x,int y){
    if(x>=0&&x<N&&y>=0&&y<=M) return true;
    else return false;
}
void dfs(int x,int y){//搜索可以到达终点的点
    can_goal[x][y]=true;
    for(int i=0;i<4;i++){
        int nx=x+dx[i],ny=y+dy[i];
        if(judge(nx,ny)&&!can_goal[nx][ny]&&grid[nx][ny]!='#')
            dfs(nx,ny);
    }
}
void solve(){
    MT(A,0);MT(b,0);MT(can_goal,false);
    dfs(N-1,M-1);//搜索可以到达终点的点

    //构建矩阵
    for(int x=0;x<N;x++){
        for(int y=0;y<M;y++)
        {
            //1.到达终点,或者(x,y)无法到达终点的情况
            if(x==N-1&&y==M-1 || !can_goal[x][y]){
                A[x*M+y][x*M+y]=1;
                continue;
            }

            //2.其余情况
            int mov=0;
            for(int k=0;k<4;k++){
                int nx=x+dx[k],ny=y+dy[k];
                if(judge(nx,ny)&&grid[nx][ny]=='.'){
                    A[x*M+y][nx*M+ny]=-1;
                    mov++;
                }
            }
            b[x*M+y]=A[x*M+y][x*M+y]=mov;
        }
    }
    Gauss(N*M,N*M);
    printf("%.8f\n",b[0]);
}
int main()
{
    while(~sff(N,M)){
        for(int i=0;i<N;i++) scanf("%s",grid[i]);
        solve();
    }
    return 0;
}
/*
从(0,0)出发,可上下左右移动,不能移动到#处。
求第一次到达(N-1,M-1)格子的期望步数。数据至少有1条能从(0,0)到达(N-1,M-1)的路径。

3 10
.#...#...#
.#.#.#.#.#
...#...#..

10 10
..........
..........
..........
..........
..........
..........
..........
..........
..........
..........

输出:
361.00000000
542.10052168
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值