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;//防我自己抄袭 
    }

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

    ありがとうございます

  • 相关阅读:
    python爬虫循环导入MySql数据库
    以洛谷P2661信息传递为例总结找环的常见的几种方法
    CF1339E-Perfect Triples (打表找规律)
    CF1339D-Edge Weight Assignment (dfs)
    CF1335E2-Three Blocks Palindrome (hard version) (二分+双指针)
    CF1327D-Infinite Path (循环置换)
    洛谷P3178 [HAOI2015]树上操作 (树链剖分)
    洛谷P2590 [ZJOI2008]树的统计 (树链剖分)
    洛谷P3833 [SHOI2012]魔法树 (树链剖分)
    树链剖分板子
  • 原文地址:https://www.cnblogs.com/Phantomhive/p/11697419.html
Copyright © 2011-2022 走看看