Yoi #379. 淘淘藍藍之樹林
阿新 • • 發佈:2020-11-26
題面
分析
要求的是某個點到圖上的點的兩條方向不同的路徑的長度的最小和
所以加入一條邊阻斷,答案為到邊上的點左邊和右邊+2的最小值
注意加入的邊不能經過起點
#include<bits/stdc++.h> const int INF=1e9; using namespace std; const int N=2005; int n,m,f[N][N],qx[N*N],qy[N*N],l,r; char a[N][N]; int dx[8]={-1,-1,-1,0,0,1,1,1}; int dy[8]={-1,0,1,-1,1,-1,0,1}; int main() { freopen("forest.in","r",stdin); freopen("forest.out","w",stdout); scanf("%d%d",&n,&m); int sx=0,sy=0,tx=0,ty; for(int i=1;i<=n;i++) { scanf("%s",a[i]+1); for(int j=1;j<=m;j++) { if(a[i][j]=='*') sx=i,sy=j; if(a[i][j]=='X'&&j!=sy&&!tx) tx=i,ty=j; } } bool fl=0; if(tx==0) { fl=1; for(int i=n;i;i--) { for(int j=m;j;j--) { if(a[i][j]=='X'&&!tx) tx=i,ty=j; } } for(int i=tx+1;i<=n;i++)a[i][ty]='X'; } else for(int i=1;i<tx;i++) a[i][ty]='X'; for(int i=0;i<=n+1;i++) { for(int j=0;j<=m+1;j++) f[i][j]=INF; } f[sx][sy]=0; qx[l=r=1]=sx,qy[1]=sy; while(l<=r) { int x=qx[l],y=qy[l]; l++; for(int i=0;i<8;i++) { int xx=x+dx[i],yy=y+dy[i]; if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&a[xx][yy]!='X'&&f[x][y]+1<f[xx][yy]) { f[xx][yy]=f[x][y]+1; qx[++r]=xx,qy[r]=yy; } } } int ans=INF; if(!fl) for(int i=1;i<tx;i++) { ans=min(ans,min(f[i][ty-1],min(f[i-1][ty-1],f[i+1][ty-1]))+min(f[i][ty+1],min(f[i-1][ty+1],f[i+1][ty+1]))+2); } else { for(int i=tx+1;i<=n;i++) { ans=min(ans,min(f[i][ty-1],min(f[i-1][ty-1],f[i+1][ty-1]))+min(f[i][ty+1],min(f[i-1][ty+1],f[i+1][ty+1]))+2); } } printf("%d\n",ans); return 0; }