题意:一个n*m(n,m<=50)的矩阵有一片连着的树林,Bessie要从起始位置出发绕林子一圈再回来,每次只能向横着、竖着或斜着走一步。问最少需多少步才能完成。
/* 如果我们用搜索来写的话,如果搜出的路径能够包围其中的一个点,那么就能包围森林,这样问题就被简化了。 我们任选一个点作为被包围点,在搜索时利用射线原理判断某这个点是否在多边形中(判断函数需要认真考虑)。 如果这条射线经过多边形奇数次,则在多边形内,否则不在。 */ #include<cstdio> #include<iostream> #include<cstring> #include<queue> #define N 60 using namespace std; char map[N][N],ch[N]; int n,m,sx,sy,gx,gy,nx,ny,tx,ty,dp[N][N][2]; int dx[8]={-1,1,0,0,-1,-1,1,1}; int dy[8]={0,0,-1,1,-1,1,-1,1}; struct node{int x,y,k;}; bool ok(){ if(tx==gx&&ty<gy){ if(nx<tx)return true; } else if(nx==gx&&ny<gy){ if(nx>tx)return true; } return false; } void bfs(){ memset(dp,-1,sizeof(dp)); queue<node> q; node u;u.x=sx;u.y=sy;u.k=0;dp[sx][sy][0]=0;q.push(u); while(!q.empty()){ u=q.front();q.pop();nx=u.x;ny=u.y;int nk=u.k,tk; for(int i=0;i<8;i++){ tx=nx+dx[i];ty=ny+dy[i];tk=nk; if(tx<1||tx>n||ty<1||ty>m||map[tx][ty]==‘X‘)continue; if(ok())tk^=1; if(dp[tx][ty][tk]==-1){ dp[tx][ty][tk]=dp[nx][ny][u.k]+1; node v;v.x=tx;v.y=ty;v.k=tk;q.push(v); } } } printf("%d\n",dp[sx][sy][1]); } int main(){ scanf("%d%d",&n,&m); bool flag=false; for(int i=1;i<=n;i++){ scanf("%s",ch); for(int j=1;j<=m;j++){ map[i][j]=ch[j-1]; if(map[i][j]==‘*‘)sx=i,sy=j; if(!flag&&map[i][j]==‘X‘)flag=1,gx=i,gy=j; } } bfs(); return 0; }
时间: 2024-10-06 07:51:38