最短路+离散化——BZOJ1967/Luogu2537 [AHOI2005]CROSS 穿越磁场

来源:互联网 发布:灌篮高手的影响力知乎 编辑:程序博客网 时间:2024/06/01 07:38

题面:BZOJ1967 Luogu2537
考虑到坐标范围非常大,但是矩阵数目很少
所以考虑离散化(离散化这个过程真的恶心
离散化的时候要注意把矩形的边左右或者上下都给留下来,这样才能给机器人跑路
离散化之后呢跑一遍spfa,注意边界处理
就是说不能连续在一条边界上面走
至于两个矩形的边交叉处不必担心,因为往交叉处走的话必定不是最优的
最后输出终点的最短路径即可

#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#include<queue>#include<cstdlib>#include<ctime>#include<climits>#include<string>using namespace std;const int dx[5]={0,1,-1,0,0};const int dy[5]={0,0,0,1,-1};struct ppap{int x,y;};queue<ppap>q;int sx,sy,zx,zy;int n,x[1001],y[1001],c[1001],nn,mm;int aa[1000005]={0},bb[1000005]={0};int disx[10001],disy[10001],dist[301][301];bool vis[301][301];int b[301][301];int ans=0;inline int read(){    int k=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();}    return k*f;}inline int spfa(int sx,int sy){    for(int i=1;i<=nn;i++)        for(int j=1;j<=mm;j++)dist[i][j]=1e9;    memset(vis,0,sizeof vis);    dist[sx][sy]=0;ppap rp;rp.x=sx;rp.y=sy;q.push(rp);    while(!q.empty()){        ppap now=q.front();q.pop();        int xx=now.x,yy=now.y;        for(int i=1;i<=4;i++){            int p,nx=xx+dx[i],ny=yy+dy[i];            if(!b[nx][ny])p=0;            else if(b[nx][ny]==b[xx][yy])continue;            else p=1;            if(dist[nx][ny]>dist[xx][yy]+p){                dist[nx][ny]=dist[xx][yy]+p;                if(!vis[nx][ny]){                    ppap pr;pr.x=nx;pr.y=ny;q.push(pr);                    vis[nx][ny]=1;                }            }        }        vis[xx][yy]=0;    }}int main(){    n=read();    for(int i=1;i<=n;i++){        x[i]=read();y[i]=read();c[i]=read();        aa[x[i]+1]=aa[x[i]]=aa[x[i]-1]=1;        bb[y[i]]=bb[y[i]-1]=bb[y[i]+1]=1;        aa[x[i]+c[i]+1]=aa[x[i]+c[i]]=aa[x[i]+c[i]-1]=1;        bb[y[i]+c[i]+1]=bb[y[i]+c[i]]=bb[y[i]+c[i]-1]=1;    }    sx=read();sy=read();zx=read();zy=read();    aa[sx]=aa[zx]=1;bb[sy]=bb[zy]=1;    int p=0,q=0;    for(int i=0;i<=1000001;i++)if(aa[i]){        q++;aa[i]=q;if(q>1)disx[q]=i-p;        p=i;    }    nn=q;p=q=0;    for(int i=0;i<=1000001;i++)if(bb[i]){        q++;bb[i]=q;if(q>1)disy[q]=i-p;        p=i;    }    mm=q;    sx=aa[sx];sy=bb[sy];zx=aa[zx];zy=bb[zy];    for(int i=1;i<=n;i++){        int xx=x[i],dx=x[i]+c[i],xy=y[i],dy=y[i]+c[i];        xx=aa[xx];xy=bb[xy];dx=aa[dx];dy=bb[dy];        for(int j=xx;j<=dx;j++)b[j][xy]=b[j][dy]=i;        for(int j=xy;j<=dy;j++)b[xx][j]=b[dx][j]=i;    }//离散化    spfa(sx,sy);    printf("%d",dist[zx][zy]);    return 0;}
原创粉丝点击