http://acm.hust.edu.cn/vjudge/contest/view.action?cid=20851#overview
I-P
其它題太水了就不寫了,這裡說一下O和P。
【我太懶不想寫】
OP這兩個題是高斯消元求期望的題。
對於P題,求從@點到$點的步數期望,先從@點BFS一遍找到所有可以到達的點,對於可達點每個點是一個變數。
因為終點有任意多而起點只有一個,這裡可以反過來求從任意一個終點走到起點的期望。
於是對於每一個終點的期望E=0。
對於其它任意一點x,走到這個點的期望 EX=sigma(ENEXT1+……+ENEXTK)/K+1
ENEXT是與X鄰接並且可達的點。
這樣建立方程組就可以求出起點到終點的期望。
對於O題,這題是走到頭再反回來,於是可以把數軸翻轉一下再接上去,比如0 1 2 …… n-1 n-2 …… 1
這樣共有2*n-2個變數,於是只要向一個方向走就可以了,同樣,終點有兩個點t和n-t,還是用和上一題一樣的方法列方程求解。
下面送上P題的代碼
int n,m;int vis[M][M],poi;char s[M][M];double a[N][N];int dx[]={0,1,0,-1};int dy[]={1,0,-1,0};bool bfs(){queue<pair<int,int> > Q;int _x,_y,flag=0;poi=1;for(int i=0;i<n;i++)for(int j=0;j<m;j++)if(s[i][j]=='@')_x=i,_y=j;Q.push(make_pair(_x,_y));vis[_x][_y]=1;while (! Q.empty()){int u=Q.front().first,v=Q.front().second;Q.pop();for(int i=0;i<4;i++){int x=u+dx[i],y=v+dy[i];if(x>=0 && x<n && y>=0 && y<m)if(s[x][y]!='#')if(! vis[x][y]){Q.push(make_pair(x,y));vis[x][y]=++poi;if(s[x][y]=='$') flag=1;}}}return flag;}int dcmp(double x){if(x>EPS) return 1;if(x<-EPS) return -1;return 0;}int guass(double a[][N],int n,int m){int i,j,k,r;double tmp;for(i=r=1;i<m;i++){for(j=r;j<=n && !dcmp(a[j][i]);j++);if(j>n) continue;if(j>r) for(k=1;k<=m;k++) swap(a[j][k],a[r][k]);for(j=1;j<=n;j++)if(j!=r && dcmp(a[j][i])){tmp=a[j][i]/a[r][i];for(k=1;k<=m;k++)a[j][k]-=tmp*a[r][k];}r++;}for(i=n;i>0;i--)if(dcmp(a[i][m])){for(j=1;j<m && !dcmp(a[i][j]);j++);if(j>=m) return -1;}return r-1;}int main(){while (scanf("%d%d",&n,&m)!=-1){for(int i=0;i<n;i++) scanf("%s",s[i]);memset(vis,0,sizeof(vis));if(! bfs()){printf("-1\n");continue;}memset(a,0,sizeof(a));for(int i=0;i<n;i++)for(int j=0;j<m;j++)if(vis[i][j]){if(s[i][j]=='$'){a[vis[i][j]][vis[i][j]]=1;continue;}int ss=0;for(int k=0;k<4;k++){int x=i+dx[k],y=j+dy[k];if(x>=0 && x<n && y>=0 && y<m)if(vis[x][y]){ss++;a[vis[i][j]][vis[x][y]]=-1;}}a[vis[i][j]][vis[i][j]]=a[vis[i][j]][poi+1]=ss;}if(guass(a,poi,poi+1)==-1) printf("-1\n");else printf("%lf\n",a[1][poi+1]/a[1][1]);}return 0;}