• ●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;
    }


     


     

  • 相关阅读:
    jq clone 克隆方法偶遇问题
    截取字符串加省略号
    瀑布流页面效果
    js 函数节流 jQuery throttle/debounce
    手机浏览页面touch操作,解决touch事件和浏览器滚动条冲突问题;zepto,swipe事件。
    touch 方向判断方法
    thinkPHP 导入栗子 (2)
    百度地图的使用实例-php+jq
    mac上配置react-native环境run-ios/run-android命令遇到的问题
    npm、cnpm、yarn 安装删除异同
  • 原文地址:https://www.cnblogs.com/zj75211/p/7967016.html
Copyright © 2020-2023  润新知