【BZOJ1967】[AHOI2005]穿越磁場(最短路)
阿新 • • 發佈:2018-10-04
truct str next sort ems emp lower ont urn
【BZOJ1967】[AHOI2005]穿越磁場(最短路)
題面
BZOJ
洛谷
題解
一個顯然的思路是這樣的,我們的正方形的邊長把整個平面割成了若幹塊,顯然每個聯通塊都可以看著做一個點,那麽接下來只需要把所有的有相鄰邊的聯通塊全部連上一條長度為\(1\)的邊表示如果要從這個聯通塊到達另外一個聯通塊,需要穿過這一條邊,那麽最終的答案就變成了起點和終點所在聯通塊的最短路。因為找聯通塊不好搞,其實離散之後再當成網格圖做就好了。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; #define ll long long #define MAX 250 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } struct Matrix{int x1,x2,y1,y2;}p[MAX<<1]; int n,Sx[MAX<<3],Sy[MAX<<3],tx,ty; int Bx,By,Ex,Ey; bool visx[MAX<<1][MAX<<1],visy[MAX<<1][MAX<<1]; struct Line{int v,next,w;}e[MAX*MAX*10]; int h[MAX*MAX<<2],cnt=1; inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;} int d[4][2]={1,0,-1,0,0,1,0,-1}; int id(int x,int y){return x*ty+y-ty;} int dis[MAX*MAX<<1];bool vis[MAX*MAX<<1]; void SPFA() { queue<int> Q;Q.push(id(Bx,By)); memset(dis,63,sizeof(dis));dis[id(Bx,By)]=0; while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=h[u];i;i=e[i].next) { int v=e[i].v; if(dis[v]>dis[u]+e[i].w) { dis[v]=dis[u]+e[i].w; if(!vis[v])vis[v]=true,Q.push(v); } } vis[u]=false; } } int main() { n=read(); for(int i=1;i<=n;++i) { int x=read(),y=read(),c=read(); p[i]=(Matrix){x,x+c,y+c,y}; } Bx=read();By=read();Ex=read();Ey=read(); Sx[++tx]=Bx;Sx[++tx]=Ex;Sy[++ty]=By;Sy[++ty]=Ey; for(int i=1;i<=n;++i)Sx[++tx]=p[i].x1,Sx[++tx]=p[i].x2; for(int i=1;i<=n;++i)Sy[++ty]=p[i].y1,Sy[++ty]=p[i].y2; sort(&Sx[1],&Sx[tx+1]);sort(&Sy[1],&Sy[ty+1]); tx=unique(&Sx[1],&Sx[tx+1])-Sx-1;ty=unique(&Sy[1],&Sy[ty+1])-Sy-1; for(int i=2;i<=tx;++i)if(Sx[i]-Sx[i-1]>1)Sx[++tx]=Sx[i]-1; for(int i=2;i<=ty;++i)if(Sy[i]-Sy[i-1]>1)Sy[++ty]=Sy[i]-1; Sx[++tx]=-10;Sy[++ty]=-10;Sx[++tx]=1e9;Sy[++ty]=1e9; sort(&Sx[1],&Sx[tx+1]);sort(&Sy[1],&Sy[ty+1]); tx=unique(&Sx[1],&Sx[tx+1])-Sx-1;ty=unique(&Sy[1],&Sy[ty+1])-Sy-1; for(int i=1;i<=n;++i) { p[i].x1=lower_bound(&Sx[1],&Sx[tx+1],p[i].x1)-Sx; p[i].x2=lower_bound(&Sx[1],&Sx[tx+1],p[i].x2)-Sx; p[i].y1=lower_bound(&Sy[1],&Sy[ty+1],p[i].y1)-Sy; p[i].y2=lower_bound(&Sy[1],&Sy[ty+1],p[i].y2)-Sy; for(int j=p[i].x1;j<=p[i].x2;++j)visx[j][p[i].y1-1]=visx[j][p[i].y2-1]=true; for(int j=p[i].y2;j<=p[i].y1;++j)visy[p[i].x1][j]=visy[p[i].x2][j]=true; } Bx=lower_bound(&Sx[1],&Sx[tx+1],Bx)-Sx;By=lower_bound(&Sy[1],&Sy[ty+1],By)-Sy; Ex=lower_bound(&Sx[1],&Sx[tx+1],Ex)-Sx;Ey=lower_bound(&Sy[1],&Sy[ty+1],Ey)-Sy; for(int i=1;i<=tx;++i) for(int j=1;j<=ty;++j) for(int k=0;k<4;++k) { int x=i+d[k][0],y=j+d[k][1]; if(x<1||y<1||x>tx||y>ty)continue; if(k==0)Add(id(i,j),id(x,y),visy[x][y]); if(k==1)Add(id(i,j),id(x,y),visy[i][j]); if(k==2)Add(id(i,j),id(x,y),visx[i][j]); if(k==3)Add(id(i,j),id(x,y),visx[x][y]); } SPFA(); printf("%d\n",dis[id(Ex,Ey)]); return 0; }
【BZOJ1967】[AHOI2005]穿越磁場(最短路)