zoukankan      html  css  js  c++  java
  • bzoj 4152[AMPPZ2014]The Captain

    bzoj 4152[AMPPZ2014]The Captain

    给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用。
    一开始我居然把这个取min看成取曼哈顿距离。。
    暴力建图是(n^2)
    考虑两个点,可以以(|x_1-x_2|)(|y_1-y_2|)为权值分别建图,在跑最短路的时候也不会去走那条权值大的边,这样就不用再管(min)
    以以(|x_1-x_2|)为权值加边为例,有三个点(i),(j),(k),(x_ileq x_jleq x_k),则(dis(i,k)=dis(i,j)+dis(j,k)),所以只要把n个点按x排序,只把相邻两个点建一条边就行了
    (|y_1-y_2|)为权值时同理
    最后跑一遍最短路
    code.

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<iomanip>
    #include<cstring>
    #define R register
    #define EN std::puts("")
    #define LL long long
    inline int read(){
    	int x=0,y=1;
    	char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    struct point{
    	int x,y,id;
    }a[200006];
    int n;
    int fir[200006],nex[800006],to[800006],w[800008],tot;
    LL dis[200006];int in[200006];
    int dui[200006],size;
    inline void push(int x){
    	dui[size++]=x;
    	R int i=size-1,fa;
    	while(i){
    		fa=i>>1;
    		if(dis[dui[fa]]<=dis[dui[i]]) return;
    		std::swap(dui[fa],dui[i]);i=fa;
    	}
    }
    inline int pop(){
    	int ret=dui[0];dui[0]=dui[--size];
    	R int i=0,ls,rs;
    	while((i<<1)<size){
    		ls=i<<1;rs=ls|1;
    		if(rs<size&&dis[dui[rs]]<dis[dui[ls]]) ls=rs;
    		if(dis[dui[ls]]>=dis[dui[i]]) break;
    		std::swap(dui[ls],dui[i]);i=ls;
    	}
    	return ret;
    }
    inline int cmpx(point aa,point bb){return aa.x<bb.x;}
    inline int cmpy(point aa,point bb){return aa.y<bb.y;}
    inline void add(int x,int y,int z){
    	to[++tot]=y;w[tot]=z;
    	nex[tot]=fir[x];fir[x]=tot;
    }
    inline void dij(){
    	std::memset(dis,0x3f,sizeof dis);
    	dis[1]=0;push(1);in[1]=1;
    	while(size){
    		R int u=pop();in[u]=0;
    		for(R int i=fir[u];i;i=nex[i]){
    			R int v=to[i];
    			if(dis[v]>dis[u]+w[i]){
    				dis[v]=dis[u]+w[i];
    				if(!in[v]) push(v),in[v]=1;
    			}
    		}
    	}
    }
    int main(){
    	n=read();
    	for(R int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),a[i].id=i;
    	std::sort(a+1,a+1+n,cmpx);
    	for(R int i=1;i<n;i++)
    		add(a[i].id,a[i+1].id,a[i+1].x-a[i].x),
    		add(a[i+1].id,a[i].id,a[i+1].x-a[i].x);
    	std::sort(a+1,a+1+n,cmpy);
    	for(R int i=1;i<n;i++)
    		add(a[i].id,a[i+1].id,a[i+1].y-a[i].y),
    		add(a[i+1].id,a[i].id,a[i+1].y-a[i].y);
    	dij();
    	std::printf("%lld",dis[n]);
    	return 0;
    }
    
  • 相关阅读:
    Yii2 的 updateAll 方法参数详解
    Yii2 数据库查询汇总
    Git常见报错
    git rebase篇
    在 Yii 2.0 上,使用 updateAll() 更新表列值为同一表的另一列值的实现
    Git从其他分支merge个别文件
    Git cherry-pick 复制多个commit
    Git 删除某次提交(某个commit)的方法
    多进程记录
    python3安装Crypto过程
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/12527517.html
Copyright © 2011-2022 走看看