蓝桥杯真题 - 邪术阵 - 题解

打印 上一主题 下一主题

主题 1057|帖子 1057|积分 3171

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
标题链接:https://www.lanqiao.cn/problems/3542/learning/
个人评价:难度 3 星(满星:5)
前置知识:迪杰斯特拉

整体思路



  • 这类标题的套路解法是把每一种状态都界说为图上的一个点,用迪杰斯特拉盘算初始状态到每一点的最短距离,通过状态之间的合法转移来盘算状态状态之间的距离;
  • 每一种状态由“节点编号”与“已选择免伤害边数”决定,界说                                         d                            i                            s                            [                            p                            o                            s                            ]                            [                            k                            ]                                  dis[pos][k]                     dis[pos][k] 表现从状态                                         d                            i                            s                            [                            0                            ]                            [                            0                            ]                                  dis[0][0]                     dis[0][0] 转移到节点                                         p                            o                            s                                  pos                     pos,已选择                                         k                                  k                     k 条免伤害边,则状态之间的距离有如下盘算方式:
                                         d                            i                            s                            [                            p                            o                            s                            ]                            [                            k                            ]                            =                                       {                                                                                                     min                                              ⁡                                              (                                              d                                              i                                              s                                              [                                              p                                              r                                                               e                                                 i                                                              ]                                              [                                              0                                              ]                                              +                                                               w                                                                   p                                                    r                                                                       e                                                       i                                                                      −                                                    p                                                    o                                                    s                                                                               )                                                                                                                            k                                              =                                              0                                                                                             o                                              r                                                                                             k                                              =                                              K                                                                                                                                                  min                                              ⁡                                              (                                              d                                              i                                              s                                              [                                              p                                              r                                                               e                                                 i                                                              ]                                              [                                              k                                              −                                              1                                              ]                                              )                                                                                                                            o                                              t                                              h                                              e                                              r                                              s                                                                                                             dis[pos][k]= \begin{cases} \min(dis[pre_i][0]+w_{pre_i-pos}) & k=0~or~k=K\\ \min(dis[pre_i][k-1]) & others \end{cases}                     dis[pos][k]={min(dis[prei​][0]+wprei​−pos​)min(dis[prei​][k−1])​k=0 or k=Kothers​


  • 此中                                         p                            r                                       e                               i                                            pre_i                     prei​ 表现节点                                         p                            o                            s                                  pos                     pos 在迪杰斯特拉过程中的第                                         i                                  i                     i 个前置节点编号;                                                   w                                           p                                  r                                               e                                     i                                              −                                  p                                  o                                  s                                                       w_{pre_i-pos}                     wprei​−pos​ 表现从节点                                         p                            r                                       e                               i                                            pre_i                     prei​ 到节点                                         p                            o                            s                                  pos                     pos 的距离                                         w                                  w                     w 的值;
  • 当                                         k                            =                            0                                  k=0                     k=0 时的递推,即完全不使用邪术,最一样平常的迪杰斯特拉写法;
  • 当                                         k                            <                            K                                  k<K                     k<K 时的递推,表现到当前节点连续选择                                         k                                  k                     k 条边的最短距离即是从前置节点往前连续选择                                         k                            −                            1                                  k-1                     k−1 条边的距离;
  • 当                                         k                            =                            K                                  k=K                     k=K 时的递推,表现之前某个时刻已经选好连续的                                         K                                  K                     K 条边了,后续无法再选择新的边,此时用一样平常的迪杰斯特拉递推写法即可;
  • 由于从起点到终点可能不到                                         K                                  K                     K 条边,大概不使用邪术的距离更短,所以终极答案为                                         min                            ⁡                            (                            d                            i                            s                            [                            N                            −                            1                            ]                            [                            K                            ]                            ,                            d                            i                            s                            [                            N                            −                            1                            ]                            [                            0                            ]                            )                                  \min(dis[N-1][K],dis[N-1][0])                     min(dis[N−1][K],dis[N−1][0])。
过题代码

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. const int maxn = 1000 + 100;
  5. struct Node {
  6.     int pos, k, dis;
  7.     Node() {}
  8.     Node(int pos, int k, int dis) : pos(pos), k(k), dis(dis) {}
  9. };
  10. bool operator<(const Node &a, const Node &b) {
  11.     return a.dis > b.dis;
  12. }
  13. int n, k, m, u, v, w;
  14. vector<Node> G[maxn];
  15. priority_queue<Node> que;
  16. int dis[maxn][100];
  17. bool vis[maxn][100];
  18. int main() {
  19. #ifdef ExRoc
  20.     freopen("test.txt", "r", stdin);
  21. #endif // ExRoc
  22.     ios::sync_with_stdio(false);
  23.     cin >> n >> k >> m;
  24.     for (int i = 0; i < m; ++i) {
  25.         cin >> u >> v >> w;
  26.         G[u].push_back(Node(v, 0, w));
  27.         G[v].push_back(Node(u, 0, w));
  28.     }
  29.     memset(dis, 0x3f, sizeof(dis));
  30.     que.push(Node(0, 0, 0));
  31.     dis[0][0] = 0;
  32.     while (!que.empty()) {
  33.         Node tmp = que.top();
  34.         que.pop();
  35.         if (vis[tmp.pos][tmp.k]) {
  36.             continue;
  37.         }
  38.         vis[tmp.pos][tmp.k] = true;
  39.         for (Node &node: G[tmp.pos]) {
  40.             // k == 0 表示不使用魔法,k == K 表示已使用过魔法
  41.             if (tmp.k == 0 || tmp.k == k) {
  42.                 if (dis[node.pos][tmp.k] > dis[tmp.pos][tmp.k] + node.dis) {
  43.                     dis[node.pos][tmp.k] = dis[tmp.pos][tmp.k] + node.dis;
  44.                     que.push(Node(node.pos, tmp.k, dis[node.pos][tmp.k]));
  45.                 }
  46.             }
  47.             // 当 k < K 时,不能不使用魔法,所以只能直接取等号
  48.             if (tmp.k < k) {
  49.                 if (dis[node.pos][tmp.k + 1] > dis[tmp.pos][tmp.k]) {
  50.                     dis[node.pos][tmp.k + 1] = dis[tmp.pos][tmp.k];
  51.                     que.push(Node(node.pos, tmp.k + 1, dis[node.pos][tmp.k + 1]));
  52.                 }
  53.             }
  54.         }
  55.     }
  56.     cout << min(dis[n - 1][0], dis[n - 1][k]) << endl;
  57.     return 0;
  58. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

郭卫东

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表