【一道来自老师的题的题解】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\n");//判断无法被兑换的情况 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("\n"); } } return 18751214;//防我自己抄袭 }
好的就是这些,由于目前没找着原题,所以无法评测,看不懂可以找我