zoukankan      html  css  js  c++  java
  • bzoj 2304: [Apio2011]寻路【spfa】

    我是智障*3,读优写错了调了半天没发现= =
    虽然是个最短路却有网络流一般的神建图啊。
    首先发现在拐角处转弯是最优的,于是先离散化,然后矩形的四个顶点向距离它最近的上下左右点连边,跑spfa即可。
    就是难写啊,还要判断无解:st在矩形里;dis[t]=inf

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<cstdlib>
    using namespace std;
    const int N=2005;
    const long long inf=1e15;
    int n,m,sx,sy,tx,ty,a[N],b[N],c[N],d[N],hax,hay,x[N],y[N],mk[N][N],tot,s,t,fx[N],fy[N],h[24005],cnt;
    long long dis[24005];
    bool v[N][N],fl[N],vis[24005];
    map<int,int>mx,my;
    struct edg
    {
    	int ne,to;
    	long long va;
    }e[200005];
    struct qwe
    {
    	int x,y,id;
    	qwe(int X=0,int Y=0,int ID=0)
    	{
    		x=X,y=Y,id=ID;
    	}
    }p[24005];
    bool cmpx(const qwe &a,const qwe &b)
    {
    	return a.x<b.x||(a.x==b.x&&a.y<b.y);
    }
    bool cmpy(const qwe &a,const qwe &b)
    {
    	return a.y<b.y||(a.y==b.y&&a.x<b.x);
    }
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    inline long long jl(qwe a,qwe b)
    {
    	return abs(fx[a.x]-fx[b.x])+abs(fy[a.y]-fy[b.y]);
    }
    void zou(int x,int y,int dx,int dy)
    {
    	x+=dx,y+=dy;
    	while(!mk[x][y])
    	{
    		if(x<1||x>hax||y<1||y>hay)
    			return;
    		x+=dx,y+=dy;
    	}
    	v[x][y]=1;
    }
    inline void add(int u,int v,long long w)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	e[cnt].va=w;
    	h[u]=cnt;
    }
    inline void ins(int u,int v,long long w)
    {//cerr<<u<<" "<<v<<" "<<w<<endl;
    	add(u,v,w);
    	add(v,u,w);
    }
    int main()
    {
    	// int T=read();
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		mx.clear(),my.clear();
    		memset(h,0,sizeof(h));
    		memset(v,0,sizeof(v));
    		memset(mk,0,sizeof(mk));
    		memset(fl,0,sizeof(fl));
    		memset(vis,0,sizeof(vis));
    		cnt=0;tot=0,hax=0,hay=0;
    		// sx=read(),sy=read(),tx=read(),ty=read(),n=read();
    		scanf("%d%d%d%d%d",&sx,&sy,&tx,&ty,&n);
    		for(int i=1;i<=n;i++)
    		{
    			// a[i]=read(),b[i]=read(),c[i]=read(),d[i]=read();
    			scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
    			if(a[i]>c[i])
    				swap(a[i],c[i]);
    			if(b[i]>d[i])
    				swap(b[i],d[i]);
    			x[i]=a[i],x[i+n]=c[i],y[i]=b[i],y[i+n]=d[i];
    		}
    		x[2*n+1]=sx,x[2*n+2]=tx,y[2*n+1]=sy,y[2*n+2]=ty;
    		sort(x+1,x+1+2*n+2);
    		sort(y+1,y+1+2*n+2);
    		for(int i=1;i<=2*n+2;i++)
    			if(i==1||x[i]!=x[i-1])
    				mx[x[i]]=++hax,fx[hax]=x[i];
    		for(int i=1;i<=2*n+2;i++)
    			if(i==1||y[i]!=y[i-1])
    				my[y[i]]=++hay,fy[hay]=y[i];//cerr<<y[i]<<" "<<my[y[i]]<<endl;
    		sx=mx[sx],sy=my[sy],tx=mx[tx],ty=my[ty];
    		mk[sx][sy]=mk[tx][ty]=-1;
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    				if(i!=j&&a[i]>=a[j]&&b[i]>=b[j]&&c[i]<=c[j]&&d[i]<=d[j])
    				{
    					fl[i]=1;
    					break;
    				}
    		for(int i=1;i<=n;i++)
    			if(!fl[i])
    			{
    				a[i]=mx[a[i]],b[i]=my[b[i]],c[i]=mx[c[i]],d[i]=my[d[i]];
    				//cerr<<a[i]<<" "<<b[i]<<" "<<c[i]<<" "<<d[i]<<endl;
    				for(int j=a[i];j<=c[i];j++)
    					mk[j][b[i]]=1,mk[j][d[i]]=2;
    				for(int j=b[i];j<=d[i];j++)
    					mk[a[i]][j]=1,mk[c[i]][j]=2;
    				mk[a[i]][b[i]]=mk[a[i]][d[i]]=mk[c[i]][b[i]]=mk[c[i]][d[i]]=-1;
    			}
    		for(int i=1;i<=n;++i)
                if((sx>a[i]&&sy>b[i]&&sx<c[i]&&sy<d[i])||(tx>a[i]&&ty>b[i]&&tx<c[i]&&ty<d[i]))
                {
                    puts("No Path");
                    return 0;
                }
    		for(int i=1;i<=n;i++)
    			if(!fl[i])
    			{
    				zou(a[i],b[i],-1,0),zou(a[i],b[i],0,-1);
    				zou(a[i],d[i],-1,0),zou(a[i],d[i],0,1);
    				zou(c[i],b[i],1,0),zou(c[i],b[i],0,-1);
    				zou(c[i],d[i],1,0),zou(c[i],d[i],0,1);
    				v[a[i]][b[i]]=v[a[i]][d[i]]=v[c[i]][b[i]]=v[c[i]][d[i]]=1;
    			}
    		v[sx][sy]=v[tx][ty]=1;
    		zou(sx,sy,-1,0),zou(sx,sy,1,0),zou(sx,sy,0,-1),zou(sx,sy,0,1);
    		zou(tx,ty,-1,0),zou(tx,ty,1,0),zou(tx,ty,0,-1),zou(tx,ty,0,1);
    		for(int i=1;i<=hax;i++)
    			for(int j=1;j<=hay;j++)
    				if(v[i][j])
    				{
    					tot++;
    					p[tot]=qwe(i,j,tot);
    					if(i==sx&&j==sy)
    						s=tot;
    					if(i==tx&&j==ty)
    						t=tot;
    				}//cerr<<s<<" "<<t<<endl;
    		sort(p+1,p+1+tot,cmpx);
    		for(int i=1,j;i<=tot;i=j)
    			for(j=i+1;j<=tot&&p[j].x==p[i].x;j++)
    				if(mk[p[j].x][p[j].y]==-1||mk[p[j-1].x][p[j-1].y]==-1||mk[p[j-1].x][p[j-1].y]>=mk[p[j].x][p[j].y])
    					ins(p[j-1].id,p[j].id,jl(p[j-1],p[j]));
    		sort(p+1,p+1+tot,cmpy);
    		for(int i=1,j;i<=tot;i=j)
    			for(j=i+1;j<=tot&&p[j].y==p[i].y;j++)
    				if(mk[p[j].x][p[j].y]==-1||mk[p[j-1].x][p[j-1].y]==-1||mk[p[j-1].x][p[j-1].y]>=mk[p[j].x][p[j].y])
    					ins(p[j-1].id,p[j].id,jl(p[j-1],p[j]));
    		queue<int>q;
    		for(int i=1;i<=tot;i++)
    			dis[i]=inf;
    		dis[s]=0;
    		vis[s]=1;
    		q.push(s);
    		while(!q.empty())
    		{
    			int u=q.front();
    			q.pop();
    			vis[u]=0;
    			for(int i=h[u];i;i=e[i].ne)
    				if(dis[e[i].to]>dis[u]+e[i].va)
    				{
    					dis[e[i].to]=dis[u]+e[i].va;
    					if(!vis[e[i].to])
    					{
    						vis[e[i].to]=1;
    						q.push(e[i].to);
    					}
    				}
    		}
    		if(dis[t]==inf)
    			puts("No Path");
    		else
    			printf("%lld
    ",dis[t]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    sqlserver 中的 substring函数(转)
    C#二个相减怎么获得天数,就是比如201225 与201231之间相差的天数
    C++文件添加到项目中
    VS2008动态链接库(DLL)的创建与导入
    美剧字幕绿箭侠第1季第7集
    C++中#define用法
    C++头文件的重复引用
    visual studio中解决方案是什么
    NewWords/300400
    指针
  • 原文地址:https://www.cnblogs.com/lokiii/p/8848248.html
Copyright © 2011-2022 走看看