zoukankan      html  css  js  c++  java
  • 2015山东信息学夏令营 Day5T3 路径

    问题描述:

    给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用。

    输入:

    第一行包含一个正整数n,表示点数。

    接下来n行,每行包含两个整数x[i],y[i](0<=x[i],y[i]<=10^9),依次表示每个点的坐标。

    输出:

    一个整数,即最小费用。

    输入输出样例:

    path.in

    path.out

    5
    2 2
    1 1
    4 5
    7 1
    6 7

    2

    数据范围:

    对于30%的数据,1<=n<=100;

    对于60%的数据,1<=n<=1000;

    对于全部的数据,1<=n<=200000;

    思路:

    1、60分直接最短路

    2、对于坐标系中连续的三个点,(x1,y1),(x2,y2),(x3,y3),总有min(x2-x1,y2-y1) + min(x3-x2,y3-y2) ≤ min(x3 -  x1,y3 - y1),所以在建图的时候,可以按x,y分别排一遍序,然后,相邻的点建边,这样边数为2*n,再用堆dij就可以了

    代码:

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #define maxn 200005
    #define inf ~0U>>1
    using namespace std;
    struct point{
        int x;
        int y;
        int pos;
    };
    struct orz{
        int p;
        int d;
        friend bool operator < (orz a,orz b){
            return a.d > b.d;
        }
    };
    struct edge{
        int v;
        int w;
    };
    priority_queue< orz > ss;
    vector<edge> g[maxn];
    point pt[maxn];
    int flag = 0,v[maxn],d[maxn],n;
    bool cmpa(point a,point b){
        return a.x < b.x;
    }
    bool cmpb(point a,point b){
        return a.y < b.y;
    }
    void init(){
        cin>>n;
        int tx,ty;
        for(int i = 1;i <= n;i++){
            scanf("%d%d",&tx,&ty);
            pt[i].x = tx;
            pt[i].y = ty;
            pt[i].pos = i;
        }
        for(int i = 1;i <= n;i++) d[i] = inf;
        sort(pt+1,pt+1+n,cmpa);
        edge tmp;
        for(int i = 1;i < n;i++){
            tmp.w = pt[i+1].x - pt[i].x;
            tmp.v = pt[i + 1].pos;
            g[pt[i].pos].push_back(tmp);
            tmp.v = pt[i].pos;
            g[pt[i+1].pos].push_back(tmp);
        }
        sort(pt+1,pt+1+n,cmpb);
        for(int i = 1;i < n;i++){
            tmp.w = pt[i+1].y - pt[i].y;
            tmp.v = pt[i + 1].pos;
            g[pt[i].pos].push_back(tmp);
            tmp.v = pt[i].pos;
            g[pt[i+1].pos].push_back(tmp);
        }
    }
    void dij(){
        orz tmp;
        d[1] = 0;
        tmp.p = 1;
        tmp.d = 0;
        ss.push(tmp);
        flag++;
        int to,wei,x,dd;
        edge j;
        while(!ss.empty()){
            tmp = ss.top();
            ss.pop();
            x = tmp.p;
            dd = tmp.d;
            if(v[x] == flag) continue;
            v[x] = flag;
            for(int i = 0;i < g[x].size();i++){
                j = g[x][i];
                to = j.v;
                wei = j.w;
                if(d[to] > dd + wei){
                    d[to] = dd + wei;
                    tmp.d = dd + wei;
                    tmp.p = to;
                    ss.push(tmp);
                }
            }
        }
        cout<<d[n];
    }
    int main(){
    
        init();
        dij();
        return 0;
    }
  • 相关阅读:
    android openGl视频
    《jQuery权威指南》学习笔记之第2章 jQuery选择器
    RobHess的SIFT源码分析:综述
    building android/ubuntu-touch on 32bit machine
    Android开发(24)---安卓中实现多线程下载(带进度条和百分比)
    创建Sdcard
    POJ 1033 Defragment
    [C++STDlib基础]关于C标准输入输出的操作——C++标准库头文件<cstdio>
    机器学习实战决策树之眼镜男买眼镜
    protubuffer for windows配置指南!
  • 原文地址:https://www.cnblogs.com/hyfer/p/5811791.html
Copyright © 2011-2022 走看看