zoukankan      html  css  js  c++  java
  • ●BOZJ 4456 [Zjoi2016]旅行者

    题链:

    http://www.lydsy.com/JudgeOnline/problem.php?id=4456

    题解:

    分治好题。
    大致做法如下:
    对于一开始的矩形区域,过较长边的中点把矩形区域分为两个块。
    然后依次以划分线上的点为起点跑最短路(Dijkstra),
    尝试以该点为中转点去更新起点和终点都在这个矩形区域内的询问。
    显然,如果某个询问的起点和终点在划分线的两侧,那么此时一定可以求出该询问的答案,
    (因为其最短路一定会经过划分线上的点)。
    那么至于起点和终点都在同侧的询问,那么就递归到更小的区域去求解是否有更优的答案,
    (因为其最短路可能不经过当前划分线上的点)。

    具体实现建议直接看代码。
    (注意在每次Dijkstra前的操作,很巧妙,可以优化时间——我也是学习网上博主的。)
    另外时间复杂度分析参见:
    http://blog.csdn.net/neither_nor/article/details/51733997
    (但复杂度分析的最后一步化简我没看太懂,QAQ)

    (不得不说,分治代码还真是考代码能力啊,调了老半天)

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define MAXN 30000
    #define MAXM 100050
    #define INF 0x3f3f3f3f 
    #define idx(i,j) (i-1)*M+j
    using namespace std;
    typedef pair<int,int>pii;
    struct Query{
    	int x1,y1,x2,y2,s,t,id;
    }q[MAXM];
    struct Edge{
    	int to[MAXM],val[MAXM],nxt[MAXM],head[MAXN],ent;
    	void Init(){ent=2;}
    	void Adde(int u,int v,int w){
    		to[ent]=v; val[ent]=w; nxt[ent]=head[u]; head[u]=ent++;
    		to[ent]=u; val[ent]=w; nxt[ent]=head[v]; head[v]=ent++;
    	}
    	int Next(int i,bool type){
    		return type?head[i]:nxt[i];
    	}
    }E;
    int N,M,Q;
    int	dis[MAXN],ans[MAXM],dx[MAXN],dy[MAXN];
    void Dijkstra(int S,int X1,int Y1,int X2,int Y2,int w){
    	static bool vis[MAXN]; static int u,v;
    	static priority_queue<pii,vector<pii>,greater<pii> >H;
    	for(int i=X1;i<=X2;i++)
    		for(int j=Y1;j<=Y2;j++){
    			u=idx(i,j);
    			w==INF?dis[u]=INF:dis[u]+=w;
    			vis[u]=0;
    		}
    	dis[S]=0; H.push(make_pair(0,S));
    	while(!H.empty()){
    		u=H.top().second; H.pop();
    		if(vis[u]) continue; vis[u]=1;
    		for(int i=E.Next(u,1);i;i=E.Next(i,0)){
    			v=E.to[i];
    			if(dx[v]<X1||dx[v]>X2||dy[v]<Y1||dy[v]>Y2) continue;
    			if(dis[v]<=dis[u]+E.val[i]) continue;
    			dis[v]=dis[u]+E.val[i]; H.push(make_pair(dis[v],v));
    		}
    	}
    }
    void Partition(int X1,int Y1,int X2,int Y2,int ql,int qr){
    	static Query tmp[MAXM];
    	if(ql>qr||X1>X2||Y1>Y2) return;
    	if(X2-X1+1<=Y2-Y1+1){
    		int mid=(Y1+Y2)/2,L=ql,R=qr,S;
    		dis[idx(X1,mid)]=INF;
    		for(int i=X1;i<=X2;i++){
    			S=idx(i,mid);
    			Dijkstra(S,X1,Y1,X2,Y2,dis[S]);
    			for(int k=ql;k<=qr;k++)
    				ans[q[k].id]=min(ans[q[k].id],dis[q[k].s]+dis[q[k].t]);
    		}
    		for(int k=ql;k<=qr;k++){
    			if(q[k].y1<mid&&q[k].y2<mid) tmp[L++]=q[k];
    			if(q[k].y1>mid&&q[k].y2>mid) tmp[R--]=q[k];
    		}
    		for(int i=ql;i<L;i++) q[i]=tmp[i];
    		for(int i=qr;i>R;i--) q[i]=tmp[i];
    		Partition(X1,Y1,X2,mid-1,ql,L-1);
    		Partition(X1,mid+1,X2,Y2,R+1,qr);
    	}
    	else{
    		int mid=(X1+X2)/2,L=ql,R=qr,S;
    		dis[idx(mid,Y1)]=INF;
    		for(int j=Y1;j<=Y2;j++){
    			S=idx(mid,j);
    			Dijkstra(S,X1,Y1,X2,Y2,dis[S]);
    			for(int k=ql;k<=qr;k++)
    				ans[q[k].id]=min(ans[q[k].id],dis[q[k].s]+dis[q[k].t]);
    		}
    		for(int k=ql;k<=qr;k++){
    			if(q[k].x1<mid&&q[k].x2<mid) tmp[L++]=q[k];
    			if(q[k].x1>mid&&q[k].x2>mid) tmp[R--]=q[k];
    		}
    		for(int i=ql;i<L;i++) q[i]=tmp[i];
    		for(int i=qr;i>R;i--) q[i]=tmp[i];
    		Partition(X1,Y1,mid-1,Y2,ql,L-1);
    		Partition(mid+1,Y1,X2,Y2,R+1,qr);
    	}
    }
    int main()
    {
    	freopen("tourist.in","r",stdin);
    	freopen("tourist.out","w",stdout);
    	E.Init();
    	scanf("%d%d",&N,&M);
    	for(int i=1;i<=N;i++)
    		for(int j=1;j<=M;j++)
    			dx[idx(i,j)]=i,dy[idx(i,j)]=j;
    	for(int i=1,w;i<=N;i++)
    		for(int j=1;j<M;j++)
    			scanf("%d",&w),E.Adde(idx(i,j),idx(i,j+1),w);
    	for(int i=1,w;i<N;i++)
    		for(int j=1;j<=M;j++)
    			scanf("%d",&w),E.Adde(idx(i,j),idx(i+1,j),w);
    	scanf("%d",&Q);
    	for(int i=1;i<=Q;i++){
    		scanf("%d%d%d%d",&q[i].x1,&q[i].y1,&q[i].x2,&q[i].y2);
    		q[i].s=idx(q[i].x1,q[i].y1);
    		q[i].t=idx(q[i].x2,q[i].y2);
    		q[i].id=i; ans[i]=INF;
    	}
    	Partition(1,1,N,M,1,Q);
    	for(int i=1;i<=Q;i++) printf("%d
    ",ans[i]);
    	return 0;
    }


     


     

  • 相关阅读:
    swoole 安装方法 使用即时聊天
    git的介绍以及简单应用
    curl的应用
    linux下监听和同步代码配置
    mac skim 修改背景色
    php 编译安装的一个 configure 配置
    mac mysql error You must reset your password using ALTER USER statement before executing this statement.
    yii2 控制器里 action 大小写组合造成的路由问题
    warning : json_decode(): option JSON_BIGINT_AS_STRING not implemented in xxx
    redis 自启动脚本
  • 原文地址:https://www.cnblogs.com/zj75211/p/7967016.html
Copyright © 2011-2022 走看看