题目链接:http://cpp.zjut.edu.cn/ShowProblem.aspx?ShowID=1423
首先对地图节点重新标号。
假设E[i]表示DK从i点开始走出迷宫的期望值。那么E[i]=(E[a1]+E[a2]+E[a3]+...+E[an])/n+1,其中a1...an是i的相邻节点。
那么对于每一个DK可达的节点来说,都可以为它建立这样的一个方程。
现在假设DK可达的点有N个,那么我们最终将会得到N元一次方程组。最后利用高斯消元解出E[num[S]]。其中S是DK的起点,num[S]是重标号后的起点
这里要重点注意的是,我们联立方程的时候,一定要注意DK可达这个条件,不然就会导致无解的情况。
#include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #include"algorithm" #include"iostream" #define exp 1e-12 using namespace std; int equ,var; double x[120]; double a[120][120]; int move[4][2]={{1,0},{0,1},{-1,0},{0,-1}}; int num[120][120]; int n,m; char map[15][15]; void debug() { for(int i=0;i<equ;i++) { for(int j=0;j<=var;j++) printf("%3.2f ",a[i][j]); puts(""); } puts(""); } struct node { int x,y; }start,end; void gauss() { int i,j; int row,col; for(row=0,col=0;row<equ&&col<var;row++,col++) { int maxr=row; for(i=row+1;i<equ;i++) if( fabs(a[i][col])>fabs(a[maxr][col])) maxr=i; for(i=0;i<=var;i++) swap(a[row][i],a[maxr][i]); for(i=row+1;i<equ;i++) { if(fabs(a[i][col])>exp) { double ta=a[i][col]/a[row][col]; for(j=col;j<=var;j++) a[i][j]-=a[row][j]*ta; } } } for(i=row-1;i>=0;i--) { double tep=a[i][var]; for(j=i+1;j<var;j++) { if(fabs(a[i][j])<=exp) continue; tep-=a[i][j]*x[j]; } x[i]=tep/a[i][i]; } } int ok(int x,int y) { if(x<0||y<0||x>=n||y>=m) return 0; if(num[x][y]!=-1) return 0; if(map[x][y]=='X') return 0; return 1; } int bfs(int x,int y) { int id=0; //id为当前点重新编号后的编号 node cur,next; cur.x=x; cur.y=y; end.x=-1; queue<node>q; q.push(cur); while(!q.empty()) { cur=q.front(); q.pop(); if(num[cur.x][cur.y]!=-1) continue; //注意去重 num[cur.x][cur.y]=id++; if(map[cur.x][cur.y]=='D') start=cur; if(map[cur.x][cur.y]=='E') end=cur; for(int i=0;i<4;i++) { next.x=cur.x+move[i][0]; next.y=cur.y+move[i][1]; if(ok(next.x,next.y)) q.push(next); } } if(end.x!=-1) return id; return -1; } int main() { while(cin>>n>>m) { int i,j,k; for(i=0;i<n;i++) cin>>map[i]; memset(num,-1,sizeof(num)); memset(a,0,sizeof(a)); int cont; for(i=0;i<n;i++) { for(j=0;j<m;j++) if(map[i][j]=='D') break; if(j!=m) break; } cont=bfs(i,j); //cont返回可到达的点的数量 if(cont==-1) //无法走到 直接返回 { puts("tragedy!"); continue; } for(i=0;i<n;i++) //每个点可到达的点与它建立期望关系 方程同题解给出 构造系数矩阵 { for(j=0;j<m;j++) { if(num[i][j]==-1) continue; if(map[i][j]=='E') { a[num[i][j]][num[i][j]]=1; continue; } int cnt=0; for(k=0;k<4;k++) { int xx=i+move[k][0]; int yy=j+move[k][1]; if(xx<0||yy<0||xx>=n||yy>=m||map[xx][yy]=='X') continue; //注意不能走要去掉。 cnt++; a[num[i][j]][num[xx][yy]]=-1; } a[num[i][j]][num[i][j]]=a[num[i][j]][cont]=cnt; } } equ=var=cont; gauss(); if(x[num[start.x][start.y]]>1000000) puts("tragedy!"); else printf("%.2f\n",x[num[start.x][start.y]]); } }
版权声明:本文为wdcjdtc原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。