zoukankan      html  css  js  c++  java
  • test20181005 迷宫 和 CF413E Maze 2D

    迷宫


    分析


    时间复杂度里的n,m写反了。
    出题人很有举一反三的精神。

    我的代码常数巨大,加了各种优化后开O3最慢点都要0.9s。

    const int INF=0x3f3f3f3f;
    
    const int MAXN=2e5+7;
    int n,m;
    int maze[6][MAXN];
    
    struct node
    {
    	int dis[6][6];
    	
    	il node()
    	{
    		memset(dis,0x3f,sizeof dis);
    	}
    	
    	il int*operator[](rg const int&x)
    	{
    		return dis[x];
    	}
    	
    	il node operator+(rg const node&rhs)const
    	{
    		rg node res;
    		for(rg int i=1;i<=n;++i)
    			for(rg int j=1;j<=n;++j)
    				for(rg int k=1;k<=n;++k)
    					res[i][j]=min(res[i][j],dis[i][k]+rhs.dis[k][j]+1);
    		return res;
    	}
    };
    
    int ql,qr;
    struct SegTree
    {
    	node data[MAXN<<2];
    	int L[MAXN<<2],R[MAXN<<2];
    #define lson (now<<1)
    #define rson (now<<1|1)
    	il void build(rg int now,rg int l,rg int r)
    	{
    		L[now]=l,R[now]=r;
    		if(l==r)
    		{
    			for(rg int i=1;i<=n;++i)
    				for(rg int j=i;j<=n;++j)
    				{
    					if(maze[j][l])
    						data[now][i][j]=data[now][j][i]=j-i;
    					else
    						break;
    				}
    			return;
    		}
    		rg int mid=(l+r)>>1;
    		build(lson,l,mid);
    		build(rson,mid+1,r);
    		data[now]=data[lson]+data[rson];
    	}
    	
    	il void change(rg int now)
    	{
    		if(L[now]==R[now])
    		{
    			memset(data[now].dis,0x3f,sizeof data[now].dis);
    			for(rg int i=1;i<=n;++i)
    				for(rg int j=i;j<=n;++j)
    				{
    					if(maze[j][L[now]])
    						data[now][i][j]=data[now][j][i]=j-i;
    					else
    						break;
    				}
    			return;
    		}
    		rg int mid=(L[now]+R[now])>>1;
    		if(ql<=mid)
    			change(lson);
    		else
    			change(rson);
    		data[now]=data[lson]+data[rson];
    	}
    	
    	il node qmin(rg int now)
    	{
    		if(ql<=L[now]&&R[now]<=qr)
    			return data[now];
    		rg int mid=(L[now]+R[now])>>1;
    		if(qr<=mid)
    			return qmin(lson);
    		if(ql>=mid+1)
    			return qmin(rson);
    		return qmin(lson)+qmin(rson);
    	}
    }T;
    
    int main()
    {
      freopen("maze.in","r",stdin);
      freopen("maze.out","w",stdout);
    	int q;
    	n=read(),m=read(),q=read();
    	for(rg int i=1;i<=n;++i)
    		for(rg int j=1;j<=m;++j)
    			maze[i][j]=read();
    	T.build(1,1,m);
    	while(q--)
    	{
    		static int opt,a,b,c,d;
    		opt=read();
    		if(opt==1)
    		{
    			a=read(),b=read();
    			maze[a][b]^=1;
    			ql=b;
    			T.change(1);
    		}
    		else
    		{
    			a=read(),b=read(),c=read(),d=read();
    			ql=b,qr=d;
    			rg int x=T.qmin(1)[a][c];
    			printf("%d
    ",x<INF?x:-1);
    		}
    	}
    //  fclose(stdin);
    //  fclose(stdout);
        return 0;
    }
    

    std的写法很优,不开O3都能0.9s。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #define rg register
    #define N 1<<19
    #define INF 0x3f3f3f3f
    char ch;void re(rg int& x)
    {
    	while(ch=getchar(),ch<'!');x=ch-48;
    	while(ch=getchar(),ch>'!')x=x*10+ch-48;
    }
    using namespace std;
    int n,m,q,l[N],r[N],p[6][N];
    struct node
    {
    	int dis[6][6];
    	node(){memset(dis,INF,sizeof dis);}
    	node operator + (const node& a)const
    	{
    		rg node tmp;
    		for(rg int i=1;i<=n;++i)
    			for(rg int j=1;j<=n;++j)
    				for(rg int k=1;k<=n;++k)
    					tmp.dis[i][j]=min(tmp.dis[i][j],dis[i][k]+a.dis[k][j]+1);
    		return tmp;
    	}
    }data[N];
    void build(rg int k,rg int a,rg int b)
    {
    	l[k]=a,r[k]=b;
    	if(a == b)
    	{
    		for(rg int i=1;i<=n;++i)
    			for(rg int j=i;j<=n;++j)
    				if(p[j][a])
    					data[k].dis[i][j]=data[k].dis[j][i]=j-i;
    				else break;
    		return;
    	}
    	build(k<<1,a,a+b>>1);
    	build(k<<1|1,(a+b>>1)+1,b);
    	data[k]=data[k<<1]+data[k<<1|1];
    }
    void change(rg int k,rg int a)
    {
    	if(l[k] == r[k])
    	{
    		memset(data[k].dis,INF,sizeof data[k].dis);
    		for(rg int i=1;i<=n;++i)
    			for(rg int j=i;j<=n;++j)
    				if(p[j][a])
    					data[k].dis[i][j]=data[k].dis[j][i]=j-i;
    				else break;	
    		return;	
    	}
    	if(a <= l[k]+r[k]>>1)change(k<<1,a);
    	else change(k<<1|1,a);
    	data[k]=data[k<<1]+data[k<<1|1];	
    }
    node solve(rg int k,rg int a,rg int b)
    {
    	if(a<=l[k] && b>=r[k])return data[k];
    	rg int mid=l[k]+r[k]>>1;
    	if(b<=mid)return solve(k<<1,a,b);
    	else if(a>mid)return solve(k<<1|1,a,b);
    	else return solve(k<<1,a,b)+solve(k<<1|1,a,b);
    }
    int main()
    {
    	freopen("maze.in","r",stdin);
    	freopen("maze.out","w",stdout);
    	re(n),re(m),re(q);
    	for(rg int i=1;i<=n;++i)
    		for(rg int j=1;j<=m;++j)	
    			re(p[i][j]);
    	build(1,1,m);
    	rg int opt,a,b,c,d;
    	while(q--)
    	{
    		re(opt),re(a),re(b);
    		if(opt == 1)
    			p[a][b]^=1,change(1,b);
    		else 
    		{
    			re(c),re(d);
    			rg int x=solve(1,b,d).dis[a][c];
    			printf("%d
    ",x<INF?x:-1);
    		}
    	}
    }
    

    Maze 2D

    The last product of the R2 company in the 2D games' field is a new revolutionary algorithm of searching for the shortest path in a (2 × n) maze.

    Imagine a maze that looks like a (2 × n) rectangle, divided into unit squares. Each unit square is either an empty cell or an obstacle. In one unit of time, a person can move from an empty cell of the maze to any side-adjacent empty cell. The shortest path problem is formulated as follows. Given two free maze cells, you need to determine the minimum time required to go from one cell to the other.

    Unfortunately, the developed algorithm works well for only one request for finding the shortest path, in practice such requests occur quite often. You, as the chief R2 programmer, are commissioned to optimize the algorithm to find the shortest path. Write a program that will effectively respond to multiple requests to find the shortest path in a (2 × n) maze.

    (n,m leq 2 cdot 10^5)

    分析

    考虑线段树,维护区间[l,r]内,四个角两两之间的距离。

    1. (d_0) 左上到右上
    2. (d_1) 左上到右下
    3. (d_2) 左下到右上
    4. (d_3) 左下到右下

    合并时(d_0=min{lson.d_0+rson.d_0,lson.d_1+rson.d_2}+1),其他同理。

    时间复杂度(O(n log n + m log n))

    const int INF=0x7fffffff;
    
    const int MAXN=2e5+7;
    int n;
    char maze[3][MAXN];
    
    int ql,qr;
    struct node
    {
    	ll d[4];
    	
    	ll&operator[](const int&x)
    	{
    		return d[x];
    	}
    	
    	node operator+(node rhs)
    	{
    		node res;
    		res[0]=min(d[0]+rhs[0],d[1]+rhs[2])+1;
    		res[1]=min(d[0]+rhs[1],d[1]+rhs[3])+1;
    		res[2]=min(d[2]+rhs[0],d[3]+rhs[2])+1;
    		res[3]=min(d[2]+rhs[1],d[3]+rhs[3])+1;
    		return res;
    	}
    };
    
    struct SegTree
    {
    	node st[MAXN<<2];
    #define lson (now<<1)
    #define rson (now<<1|1)
    	void build(int now,int l,int r)
    	{
    		if(l==r)
    		{
    			int x=(maze[1][l]=='.'),y=(maze[2][l]=='.');
    			st[now][0]=x?0:2*n;
    			st[now][1]=st[now][2]=x&&y?1:2*n;
    			st[now][3]=y?0:2*n;
    			return;
    		}
    		int mid=(l+r)>>1;
    		build(lson,l,mid);
    		build(rson,mid+1,r);
    		st[now]=st[lson]+st[rson];
    	}
    	
    	node qmin(int now,int l,int r)
    	{
    /*		cerr<<"qmin "<<now<<" "<<l<<" -> "<<r<<endl;
    		if(now==0)
    			system("pause");*/
    		if(ql<=l&&r<=qr)
    			return st[now];
    		int mid=(l+r)>>1;
    		if(qr<=mid)
    			return qmin(lson,l,mid);
    		if(ql>=mid+1)
    			return qmin(rson,mid+1,r);
    		return qmin(lson,l,mid)+qmin(rson,mid+1,r);
    	}
    }T;
    
    int main()
    {
    //  freopen("CF413E.in","r",stdin);
    //  freopen(".out","w",stdout);
    	int m;
    	read(n);read(m);
    	scanf("%s",maze[1]+1);
    	scanf("%s",maze[2]+1);
    /*	cerr<<"maze="<<endl;
    	cerr<<(maze[1]+1)<<endl;
    	cerr<<(maze[2]+1)<<endl;*/
    	T.build(1,1,n);
    	while(m--)
    	{
    		int u,v;
    		read(u);read(v);
    		if((u-1)%n+1>(v-1)%n+1)
    			swap(u,v);
    //		cerr<<"u="<<u<<" v="<<v<<endl;
    		int x1=(u>n)+1,x2=(v>n)+1;
    		ql=u-(x1-1)*n,qr=v-(x2-1)*n; // edit 1
    //		cerr<<"("<<x1<<" , "<<ql<<") -> ("<<x2<<" , "<<qr<<")"<<endl;
    		node ans=T.qmin(1,1,n);
    //		cerr<<"d="<<((x1-1)<<1|(x2-1))<<endl;
    		if(ans[(x1-1)<<1|(x2-1)]<2*n)
    			printf("%lld
    ",ans[(x1-1)<<1|(x2-1)]);
    		else
    			puts("-1");
    	}
    //  fclose(stdin);
    //  fclose(stdout);
        return 0;
    }
    

    考虑边界的时候base0和base1混用导致主函数代码很丑,将就着看。

    注意给路径不通赋值时如果赋成2n要开long long

    静渊以有谋,疏通而知事。
  • 相关阅读:
    前端从头再出发之表单
    百度前端学院第19天作业
    百度前端学院第17到18天和第16天的作业
    百度前端学院第九天到第11天笔记
    自己爬虫的几个案例
    Magnum Kubernetes源码分析(一)
    magnum devstack部署
    kubernetes service分析
    玩转docker镜像和镜像构建
    Dockerfile与Docker构建流程解读
  • 原文地址:https://www.cnblogs.com/autoint/p/9746078.html
Copyright © 2011-2022 走看看