zoukankan      html  css  js  c++  java
  • 【一道来自老师的题的题解】equip——奇妙的最短路

    这道题真的第一眼完全想不到是最短路啊!!!!!!!!

    感谢DR大佬讲解!!!!!90°鞠躬 =u=

     暂时没有评测网址,(因为需要special judge)敬请期待

    机房另一大佬JYY题解,可以对比参照(说不定就会了呢)<-点这个

    (她的博客里有一些问题答疑不懂得去看看哈)


    题面:

     分析过程依旧来源于老师

     为什么可以连图的证明过程忽略(因为我不会

    这张图基本就是所有能被表示的数,求出的最短路就是最小能被表示的数,由于它们都对 a[1] 取模,根据这点可以用已求出的数据计算出每种碎片的使用情况,(我们默认能多用 a[1] 就多用)这题是“任意一种方案即可”,所以我们不用考虑“用 n 个 a[ j ] 可以表示 a[ i ] ”的情况

    参考代码可能会便于理解思路(代码有超级超级详细的注释哦真的不看看嘛)

    /*数组变量解释:
     dis 存放最短路值,pre 存放每个价值所用的碎片编号, vis , sum 代码中都有详细解释
    */
    #include<bits/stdc++.h>
    #define A 20001
    #define N 5001
    using namespace std;
    typedef long long ll;
    struct node 
    {
        int x; ll v;
        bool operator < (const node &oth) const 
        {
            return v > oth.v;
        }//重载运算符实现大根堆 
    };
    priority_queue<node>q;
    int pre[A], n, m, K, vis[A];
    ll a[N], dis[A], sum[N];
    ll getin() 
    {
        ll s = 0; char c = getchar();
        while (c < '0' || c > '9') c = getchar();
        while (c <= '9' && c >= '0') s = s * 10ll + c - '0', c = getchar();
        return s;
    }//快读忽略 
    void dijkstra() 
    {
        for (int i = 1; i < a[1]; i++) dis[i] = 1e18;
        dis[0] = 0;
        q.push((node) {0, 0});
        //赋初值 
        while (!q.empty())
        {
            int u = q.top().x;//这是当前的点 
            q.pop();
            if (vis[u]) continue;
            vis[u] = true;
            // vis数组用来判断是否更新 
            //参考dijsktra 
            for (int i = 1; i <= n; i++)
             {
                int v = (u + a[i]) % a[1];//目前的需要更新的点 
                if (dis[u] + a[i] < dis[v])
                {
                    dis[v] = dis[u] + a[i];//判断是否需要更新 
                    pre[v] = i; //这个正在更新的点边权(a[j]) 的编号 J 
                    q.push((node){v, dis[v]});//加入堆 
                }
            }
        }
    }
    int main() {
        //freopen("equip.in", "r", stdin);
        //freopen("equip.out", "w", stdout);
        scanf("%d%d%d", &n, &m, &K);
        for (int i = 1; i <= n; i++) a[i] = getin();
        dijkstra();
        for (int i = 1; i <= m; i++) {
            ll x = getin();
            if (x < dis[x % a[1]]) printf("No
    ");//判断无法被兑换的情况 
            else {
                printf("Yes");
                if (K == 1) {
                    for (int j = 1; j <= n; j++) sum[j] = 0;
                    //sum[j] 表示的是每种碎片需要的数量 
                    sum[1] += (x - dis[x % a[1]]) / a[1];
                    //需要的 a[1] 碎片数量 
                    // x-dis[x%a[1]] 是刨掉a[1]以外碎片使用的总价值 
                    while (x % a[1]) 
                    {
                        sum[pre[x % a[1]]]++;//这个位置的碎片数++; 
                        x = ((x - a[pre[x % a[1]]]) % a[1] + a[1]) % a[1];
                        //把当前的碎片和a[1]刨掉剩下的需要价值(那么长主要是保证其精度不要在意) 
                    }
                    for (int j = 1; j <= n; j++) printf(" %I64d", sum[j]);
                    //简简单单的输出,不用的话就是输出0 (反正任意一种情况都能过2333) 
                }
                printf("
    ");
            }
        }
        return 18751214;//防我自己抄袭 
    }

    好的就是这些,由于目前没找着原题,所以无法评测,看不懂可以找我

    ありがとうございます

  • 相关阅读:
    BestCoder17 1001.Chessboard(hdu 5100) 解题报告
    codeforces 485A.Factory 解题报告
    codeforces 485B Valuable Resources 解题报告
    BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告
    codeforces 374A Inna and Pink Pony 解题报告
    codeforces 483B Friends and Presents 解题报告
    BestCoder15 1002.Instruction(hdu 5083) 解题报告
    codeforces 483C.Diverse Permutation 解题报告
    codeforces 483A. Counterexample 解题报告
    NSArray中地内存管理 理解
  • 原文地址:https://www.cnblogs.com/Phantomhive/p/11697419.html
Copyright © 2011-2022 走看看