/*这题是求期望,我们把每一个格子看成一个点,
那么对于每一个点,他到E的期望可以用递推公式来表示
对于E点,他的期望是0
对于那些S到不了的点,都设置成-1
然后列方程
比如,某个点k,可以到i1,i2,i3,i4这么四个点
那么f[k]=(f[i1]+1)/4+(f[i2]+1)/4+(f[i3]+1)/4+(f[i4]+1)/4
这样对于每一个点可以列出方程,最后有n*m个方程,然后高斯消元去。
复杂度O((n*m)^3)*/
#include <cstdio>
#include <string>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <map>
#include <queue>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long lld;
const int INF=1000000000;
const int MAX=1000;
const double EPS=1.0e-8;
bool vis[20][20];
char s[MAX][MAX];
const int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
bool ok(int x,int n){return x>=0&&x<n;}
queue< pair<int,int> >q;
bool BFS(int x,int y,int n,int m)
{
bool flag=false;
memset(vis,false,sizeof(vis));
while(!q.empty())q.pop();
vis[x][y]=true;
q.push(make_pair(x,y));
int tx,ty;
while(!q.empty())
{
x=q.front().first;
y=q.front().second;
q.pop();
for(int i=0;i<4;i++)
{
tx=x+dir[i][0];
ty=y+dir[i][1];
if(!ok(tx,n)||!ok(ty,m))continue;
if(s[tx][ty]=='#')continue;
if(vis[tx][ty])continue;
vis[tx][ty]=true;
q.push(make_pair(tx,ty));
if(s[tx][ty]=='E')flag=true;
}
}
return flag;
}
int dblcmp(double x)
{
if(fabs(x)<EPS)return 0;
return x<0?-1:1;
}
double mat[MAX][MAX];
int _find(int s,int n,int mainx)
{
int i;
for(i=s+1;i<n;i++)
{
if(dblcmp(mat[i][mainx])!=0)return i;
}
return -1;
}
void swap(int a,int b,int n,int s)
{
int i=0;
for(i=s;i<n;i++)
{
swap(mat[a][i],mat[b][i]);
}
}
double ans[MAX];
int GAUSS(int n,int m)
{
int i,j,k;
int mainx=0;
for(i=0;i<n&&mainx<m-1;i++,mainx++)
{
if(dblcmp(mat[i][mainx])==0)
{
j=_find(i,n,mainx);
if(j==-1)
{
i--;
continue;
}
else
{
swap(i,j,m,mainx);
}
}
double tmp=1.0/mat[i][mainx];
if(dblcmp(mat[i][mainx]-1)!=0)
{
for(j=i;j<m;j++)
{
mat[i][j]*=tmp;
}
}
for(j=i+1;j<n;j++)
{
tmp=mat[j][mainx]/mat[i][mainx];
for(k=i;k<m;k++)
{
mat[j][k]-=mat[i][k]*tmp;
}
}
}
//out(n,m);
int zeroRow=0;
//判断无解
for(i=0;i<n;i++)
{
int sum=0;
for(j=0;j<m-1;j++)
{
//sum+=mat[i][j];
if(dblcmp(mat[i][j])!=0)
{
sum=1;
break;
}
}
if(sum==0&&dblcmp(mat[i][m-1])!=0)
{
return -1;
}
else if(sum==0)
{
zeroRow++;
}
}
if(n-zeroRow!=m-1)return 0;
n-=zeroRow;
for(i=n-1;i>=0;i--)
{
double sum=0;
for(j=i+1;j<m-1;j++)
{
sum+=mat[i][j]*ans[j];
}
mat[i][m-1]-=sum;
ans[i]=mat[i][m-1];
}
return 1;
}
void build(int x,int y,int n,int m)
{
int i,tx,ty;
int ps=x*m+y;
int pt;
if(s[x][y]=='#'||!vis[x][y])
{
mat[ps][ps]=1;
mat[ps][m*n]=-1;
return ;
}
if(s[x][y]=='E')
{
mat[ps][ps]=1;
mat[ps][n*m]=0;
return ;
}
int cnt=0;
for(i=0;i<4;i++)
{
tx=x+dir[i][0];
ty=y+dir[i][1];
if(!ok(tx,n)||!ok(ty,m))continue;
if(s[tx][ty]=='#')continue;
cnt++;
}
if(cnt==0)
{
mat[ps][ps]=1;
mat[ps][m*n]=-1;
return ;
}
mat[ps][ps]=1;
mat[ps][n*m]=1;
double rat=1.0/cnt;
for(i=0;i<4;i++)
{
tx=x+dir[i][0];
ty=y+dir[i][1];
if(!ok(tx,n)||!ok(ty,m))continue;
if(s[tx][ty]=='#')continue;
pt=tx*m+ty;
mat[ps][pt]=-rat;
}
}
void out(int n,int m)
{
return;
int i,j;
puts("start");
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
printf("%.3f ",mat[i][j]);
}
puts("");
}
puts("end");
}
int main()
{
int n=4;
int T,i,j,k;
int m;
int pos;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=0;i<n;i++)
{
scanf("%s",s[i]);
for(j=0;j<m;j++)
{
if(s[i][j]=='S')
{
pos=i*m+j;
}
}
}
if(!BFS(pos/m,pos%m,n,m))
{
puts("-1");
continue;
}
int N=n*m;
for(i=0;i<N;i++)
{
for(j=0;j<=N;j++)
{
mat[i][j]=0;
}
mat[i][i]=1;
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
build(i,j,n,m);
}
}
out(N,N+1);
if(GAUSS(N,N+1)!=1)
{
puts("-1");
continue;
}
if(dblcmp(ans[pos]+1)==0)puts("-1");
else printf("%.2f\n",ans[pos]);
}
return 0;
}
那么对于每一个点,他到E的期望可以用递推公式来表示
对于E点,他的期望是0
对于那些S到不了的点,都设置成-1
然后列方程
比如,某个点k,可以到i1,i2,i3,i4这么四个点
那么f[k]=(f[i1]+1)/4+(f[i2]+1)/4+(f[i3]+1)/4+(f[i4]+1)/4
这样对于每一个点可以列出方程,最后有n*m个方程,然后高斯消元去。
复杂度O((n*m)^3)*/
#include <cstdio>
#include <string>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <map>
#include <queue>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long lld;
const int INF=1000000000;
const int MAX=1000;
const double EPS=1.0e-8;
bool vis[20][20];
char s[MAX][MAX];
const int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
bool ok(int x,int n){return x>=0&&x<n;}
queue< pair<int,int> >q;
bool BFS(int x,int y,int n,int m)
{
bool flag=false;
memset(vis,false,sizeof(vis));
while(!q.empty())q.pop();
vis[x][y]=true;
q.push(make_pair(x,y));
int tx,ty;
while(!q.empty())
{
x=q.front().first;
y=q.front().second;
q.pop();
for(int i=0;i<4;i++)
{
tx=x+dir[i][0];
ty=y+dir[i][1];
if(!ok(tx,n)||!ok(ty,m))continue;
if(s[tx][ty]=='#')continue;
if(vis[tx][ty])continue;
vis[tx][ty]=true;
q.push(make_pair(tx,ty));
if(s[tx][ty]=='E')flag=true;
}
}
return flag;
}
int dblcmp(double x)
{
if(fabs(x)<EPS)return 0;
return x<0?-1:1;
}
double mat[MAX][MAX];
int _find(int s,int n,int mainx)
{
int i;
for(i=s+1;i<n;i++)
{
if(dblcmp(mat[i][mainx])!=0)return i;
}
return -1;
}
void swap(int a,int b,int n,int s)
{
int i=0;
for(i=s;i<n;i++)
{
swap(mat[a][i],mat[b][i]);
}
}
double ans[MAX];
int GAUSS(int n,int m)
{
int i,j,k;
int mainx=0;
for(i=0;i<n&&mainx<m-1;i++,mainx++)
{
if(dblcmp(mat[i][mainx])==0)
{
j=_find(i,n,mainx);
if(j==-1)
{
i--;
continue;
}
else
{
swap(i,j,m,mainx);
}
}
double tmp=1.0/mat[i][mainx];
if(dblcmp(mat[i][mainx]-1)!=0)
{
for(j=i;j<m;j++)
{
mat[i][j]*=tmp;
}
}
for(j=i+1;j<n;j++)
{
tmp=mat[j][mainx]/mat[i][mainx];
for(k=i;k<m;k++)
{
mat[j][k]-=mat[i][k]*tmp;
}
}
}
//out(n,m);
int zeroRow=0;
//判断无解
for(i=0;i<n;i++)
{
int sum=0;
for(j=0;j<m-1;j++)
{
//sum+=mat[i][j];
if(dblcmp(mat[i][j])!=0)
{
sum=1;
break;
}
}
if(sum==0&&dblcmp(mat[i][m-1])!=0)
{
return -1;
}
else if(sum==0)
{
zeroRow++;
}
}
if(n-zeroRow!=m-1)return 0;
n-=zeroRow;
for(i=n-1;i>=0;i--)
{
double sum=0;
for(j=i+1;j<m-1;j++)
{
sum+=mat[i][j]*ans[j];
}
mat[i][m-1]-=sum;
ans[i]=mat[i][m-1];
}
return 1;
}
void build(int x,int y,int n,int m)
{
int i,tx,ty;
int ps=x*m+y;
int pt;
if(s[x][y]=='#'||!vis[x][y])
{
mat[ps][ps]=1;
mat[ps][m*n]=-1;
return ;
}
if(s[x][y]=='E')
{
mat[ps][ps]=1;
mat[ps][n*m]=0;
return ;
}
int cnt=0;
for(i=0;i<4;i++)
{
tx=x+dir[i][0];
ty=y+dir[i][1];
if(!ok(tx,n)||!ok(ty,m))continue;
if(s[tx][ty]=='#')continue;
cnt++;
}
if(cnt==0)
{
mat[ps][ps]=1;
mat[ps][m*n]=-1;
return ;
}
mat[ps][ps]=1;
mat[ps][n*m]=1;
double rat=1.0/cnt;
for(i=0;i<4;i++)
{
tx=x+dir[i][0];
ty=y+dir[i][1];
if(!ok(tx,n)||!ok(ty,m))continue;
if(s[tx][ty]=='#')continue;
pt=tx*m+ty;
mat[ps][pt]=-rat;
}
}
void out(int n,int m)
{
return;
int i,j;
puts("start");
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
printf("%.3f ",mat[i][j]);
}
puts("");
}
puts("end");
}
int main()
{
int n=4;
int T,i,j,k;
int m;
int pos;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=0;i<n;i++)
{
scanf("%s",s[i]);
for(j=0;j<m;j++)
{
if(s[i][j]=='S')
{
pos=i*m+j;
}
}
}
if(!BFS(pos/m,pos%m,n,m))
{
puts("-1");
continue;
}
int N=n*m;
for(i=0;i<N;i++)
{
for(j=0;j<=N;j++)
{
mat[i][j]=0;
}
mat[i][i]=1;
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
build(i,j,n,m);
}
}
out(N,N+1);
if(GAUSS(N,N+1)!=1)
{
puts("-1");
continue;
}
if(dblcmp(ans[pos]+1)==0)puts("-1");
else printf("%.2f\n",ans[pos]);
}
return 0;
}