zoukankan      html  css  js  c++  java
  • bzoj P1979 华容道【bfs+spfa】

    调死我了……
    首先观察移动方式,需要移动的格子每次移动到相邻格子,一定是先把空白格子挪过去,所以我们得到一种做法,就是bfs预处理出每一个格子的四联通格子之间的空白格子移动距离建边,注意这个移动是不能经过当前枚举的中心格子的,然后把中心格子和它的四联通格子建边权为1的边
    注意这里用来建边的点,是(x,y,k),表示当前在格子(x,y),空白格子在k方向
    然后对于询问,先bfs出把空白格子移动到起始格子周围的步数,然后再spfa即可
    然后对于

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int N=35,dx[]={-1,1,0,0},dy[]={0,0,-1,1};
    int n,m,q,c[N][N],inf,dis[N][N],h[100005],cnt,d[100005],id[N][N][5],tot;
    bool v[100005],vis[N][N][5];
    struct dian
    {
    	int x,y;
    	dian(int X=0,int Y=0)
    	{
    		x=X,y=Y;
    	}
    };
    struct qwe
    {
    	int ne,to,va;
    }e[1000005];
    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;
    }
    void add(int u,int v,int w)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	e[cnt].va=w;
    	h[u]=cnt;
    }
    bool ok(int x,int y)
    {
    	return x>=1&&x<=n&&y>=1&&y<=m&&c[x][y];
    }
    void bfs(int x,int y,int lx,int ly,int l)
    {
    	memset(dis,0,sizeof(dis));
    	queue<dian>q;
    	dis[x][y]=1;
    	q.push(dian(x,y));
    	while(!q.empty())
    	{
    		int x=q.front().x,y=q.front().y;
    		q.pop();
    		for(int i=0;i<4;i++)
    			if(ok(x+dx[i],y+dy[i])&&!dis[x+dx[i]][y+dy[i]]&&(x+dx[i]!=lx||y+dy[i]!=ly))
    			{
    				dis[x+dx[i]][y+dy[i]]=dis[x][y]+1;
    				q.push(dian(x+dx[i],y+dy[i]));
    			}
    	}
    	// cerr<<x<<" "<<y<<"   "<<lx<<" "<<ly<<endl;
    	// for(int i=1;i<=n;i++)
    	// {
    		// for(int j=1;j<=m;j++)
    			// cerr<<dis[i][j]<<" ";
    		// cerr<<endl;
    	// }
    	// cerr<<endl;
    	if(l==4)
    		return;
    	for(int i=0;i<4;i++)
    		if(i!=l&&ok(lx+dx[i],ly+dy[i])&&dis[lx+dx[i]][ly+dy[i]])
    			add(id[lx][ly][l],id[lx][ly][i],dis[lx+dx[i]][ly+dy[i]]-1);
    	add(id[lx][ly][l],id[x][y][l^1],1);
    }
    int spfa(int x,int y)
    {
    	queue<int>q;
    	for(int i=0;i<=tot;i++)
    		d[i]=1e9,v[i]=0;
    	for(int i=0;i<4;i++)
    		if(ok(x+dx[i],y+dy[i])&&dis[x+dx[i]][y+dy[i]])
    		{
    			d[id[x][y][i]]=dis[x+dx[i]][y+dy[i]]-1;
    			v[id[x][y][i]]=1;
    			q.push(id[x][y][i]);
    		}
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		v[u]=0;
    		for(int i=h[u];i;i=e[i].ne)
    			if(d[e[i].to]>d[u]+e[i].va)
    			{
    				d[e[i].to]=d[u]+e[i].va;
    				if(!v[e[i].to])
    				{
    					v[e[i].to]=1;
    					q.push(e[i].to);
    				}
    			}
    	}
    }
    int main()
    {
    	n=read(),m=read(),q=read();
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    		{
    			c[i][j]=read();
    			for(int k=0;k<4;k++)
    				id[i][j][k]=++tot;
    		}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			if(c[i][j])
    				for(int k=0;k<4;k++)
    					if(ok(i+dx[k],j+dy[k]))
    						bfs(i+dx[k],j+dy[k],i,j,k);
    	while(q--)
    	{
    		int ex=read(),ey=read(),sx=read(),sy=read(),tx=read(),ty=read();
    		if(sx==tx&&sy==ty)
    		{
    			puts("0");
    			continue;
    		}
    		bfs(ex,ey,sx,sy,4);
    		spfa(sx,sy);
    		int ans=1e9;
    		for(int i=0;i<4;i++)
    			ans=min(ans,d[id[tx][ty][i]]);
    		if(ans==1e9)
    			puts("-1");
    		else
    			printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Neo4j电影关系图Cypher
    Neo4j电影关系图
    Neo4j配置文件neo4j.conf
    SpringBoot实现多数据源(实战源码)
    Maven添加Oracle驱动及依赖
    HttpClient发送Json数据到指定接口
    java手动分页处理
    设计模式之模板方法模式
    JDBC插入性能优化对比
    Oracle数据库常用监控语句
  • 原文地址:https://www.cnblogs.com/lokiii/p/9638659.html
Copyright © 2011-2022 走看看