您的位置:首页 > 其它

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

2015-08-03 11:02 429 查看
从(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
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: