• CCPC-Wannafly Winter Camp Day1 爬爬爬山 (最短路)


    题目描述

     

    爬山是wlswls最喜欢的活动之一。

    在一个神奇的世界里,一共有nn座山,mm条路。

    wlswls初始有kk点体力,在爬山的过程中,他所处的海拔每上升1m1m,体力会减11点,海拔每下降1m1m,体力会加一点。

    现在wlswls想从11号山走到nn号山,在这个过程中,他的体力不能低于00,所以他可以事先花费一些费用请dlsdls把某些山降低,将一座山降低ll米需要花费l*lll的代价,且每座山的高度只能降低一次。因为wlswls现在就在11号山上,所以这座山的高度不可降低。

    wlswls从11号山到nn号山的总代价为降低山的高度的总代价加上他走过的路的总长度。

    wlswls想知道最小的代价是多少。

    输入描述

     

    第一行三个整数nn,mm,kk。

    接下来一行nn个整数,第ii个整数h_ihi表示第ii座山的高度。

    接下来mm行,每行三个整数xx,yy,zz表示xyxy之间有一条长度为zz的双向道路。

    经过每条路时海拔是一个逐步上升或下降的过程。

    数据保证11号山和nn号山联通。

    1 leq n, k, h_i, z leq 1000001n,k,hi,z100000

    1 leq m leq 2000001m200000

    1 leq x, y leq n1x,yn

    x eq yx=y

    输出描述

     

    一行一个整数表示答案。

    样例输入 1 

    4 5 1
    1 2 3 4
    1 2 1
    1 3 1
    1 4 100
    2 4 1
    3 4 1

    样例输出 1

    6


    题意:
    定义两个山i,j之间的消耗dist(i,j) 我们通过题意应该知道,dist不仅仅与题中给距离有关,
    还与山i和j的高度差 h 有关,如果h大于k,那么需要多消耗 (h-k)*(h-k) 。
    我们依据上述的距离关系来跑最短路算法,即可得到我们想要的答案。
    细节见代码:
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define rt return
    #define dll(x) scanf("%I64d",&x)
    #define xll(x) printf("%I64d
    ",x)
    #define sz(a) int(a.size())
    #define all(a) a.begin(), a.end()
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
    using namespace std;
    typedef long long ll;
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
    ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
    inline void getInt(int* p);
    const int maxn = 1000010;
    const int inf = 0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    
    int n, m;
    ll k;
    struct node
    {
        int to;
        ll dist;
        int next;
        node() {}
        node(int tt, ll dd)
        {
            to = tt;
            dist = dd;
        }
        bool operator < (const node x)const {
            return dist > x.dist;
        }
    };
    priority_queue<node> heap;
    int tot;
    node edge[maxn];
    int head[maxn];
    void addedge(int u, int v, int dist)
    {
        edge[tot].dist = dist;
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    void init()
    {
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    ll h[maxn];
    ll dis[maxn];
    void dijkstra(int start)
    {
        // memset(dis,inf,sizeof(dis));
        repd(i, 1, n)
        {
            dis[i] = 1e18;
        }
        dis[start] = 0;
        heap.push(node(start, 0ll));
        node temp;
        while (!heap.empty())
        {
            temp = heap.top();
            heap.pop();
            for (int i = head[temp.to]; i != -1; i = edge[i].next)
            {
                int v = edge[i].to;
                if (h[v] > k)
                {
                    if (dis[v] > temp.dist + edge[i].dist + (h[v] - k) * (h[v] - k))
                    {
                        dis[v] = temp.dist + edge[i].dist + (h[v] - k) * (h[v] - k);
                        heap.push(node(edge[i].to, dis[v]));
                    }
                } else
                {
                    if (dis[v] > temp.dist + edge[i].dist)
                    {
                        dis[v] = temp.dist + edge[i].dist;
                        heap.push(node(edge[i].to, dis[v]));
                    }
                }
            }
        }
    }
    int main()
    {
        //freopen("D:\common_text\code_stream\in.txt","r",stdin);
        //freopen("D:\common_text\code_stream\out.txt","w",stdout);
    
        gbtb;
        cin >> n >> m >> k;
        repd(i, 1, n)
        {
            cin >> h[i];
        }
        repd(i, 2, n)
        {
            h[i] -= h[1]; // 减去初始的高度方便后面处理
        }
        init(); // 初始化链式前向星
        int u, v, d;
        repd(i, 1, m)
        {
            cin >> u >> v >> d;
            addedge(u, v, d); // 加边
            addedge(v, u, d);
        }
        dijkstra(1);// 跑最短路
        cout << dis[n] << endl; // 输出答案
    
        return 0;
    }
    
    inline void getInt(int* p) {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        }
        else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }


    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    objective-c数组
    objective-c可变数组
    objective-c可变字典
    objective-c字典
    有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
    将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5
    一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?
    求123456789-23456789-3456789-456789-...-9的值
    编写一个程序,求s=1+(1+2)+(1+2+3)+…+(1+2+3+…+n)的值
    Unity3D笔记 GUI 二 、实现选项卡一窗口
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/10896734.html
Copyright © 2020-2023  润新知