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

    静渊以有谋,疏通而知事。
  • 相关阅读:
    Kendo UI开发教程(8): Kendo UI 特效概述
    6.3 计算字符在字符串中出现的次数
    有意思的GacUI
    Qt信号量QSemaphore(在线程里使用,结合生产者消费者的问题)
    Qt 自定义事件详细实例(继承QEvent,然后QCoreApplication::postEvent()、sendEvent())
    为什么选择使用 Dropbox 而不是其他品牌同步工具(不要加上多余的功能,要极致和专注)
    DropBox与Box的区别,包括直接的投资人的评价(本地Sync可能还是挺重要的)
    ASP.NET所谓前台调用后台、后台调用前台想到HTTP——实践篇
    8个免费实用的C++GUI库
    .NET 利用反射将对象数据添加到数据库
  • 原文地址:https://www.cnblogs.com/autoint/p/9746078.html
Copyright © 2011-2022 走看看