• 加满油箱问题


    一 问题描述

    城市之间的油价是不一样的,编写程序,寻找最便宜的城市间的旅行方式。在旅行途中可以加满油箱。假设汽车每单位距离使用一单位燃料,从一个空油箱开始。

    二 输入和输出

    1 输入

    输入的第 1 行包含 n 和 m,表示城市和道路的数量。下一行包含 n 个整数 pi,其中 pi 表示第 i 个城市的燃油价格。接下来的 m 行,每行都包含 3 个整数 u,v 和 d,表示在 u 和 v 之间有一条路,长度为 d。接下来一行是查询数 q。再接下来是 q 行,每行都包含 3 个整数 c、s 和 e,其中 c 是车辆的邮箱容量,s 是起点城市,e 是终点城市。

    2 输出

    对于每个查询,都输出给定容量的汽车从 s 到 e 的最便宜旅程的价格,如果无法从 s 到 e,则输出 "impossible"。

    三 输入和输出样例

    1 输入样例

    5 5

    10 10 20 12 13

    0 1 9

    0 2 8

    1 2 1

    1 3 11

    2 3 7

    2

    10 0 3

    20 1 4

    2 输出样例

    170

    impossible

    四 分析

    本问题为加油站加油问题。给定 n 个节点、m 条边,每走 1 单位的路径都会花费 1 单位的油量,并且不同的加油站价格是不同的。现在有一些询问,每一个询问都包括起点和终点及邮箱的容量,求从起点到终点所需的最少花费。可以采用优先队列分支限界法搜索。

    涉及两个维度的图的最短路径,一个是费用,一个是地点。可以把当前节点对应的油量成多个节点(例如在位置 0 有 1 升油是一个节点,在位置 0 有 2 升油是一个节点),把费用看作边:每次都加 1 升油;如果依靠加的油能够走到下一个节点,就走到下一个节点(减去路上消耗的油,花费不变);在广度优先搜索中将所有可扩展的节点都加入优先队列中,如果达到终点,则返回花费。

    五 算法设计

    1 定义一个优先队列,将起点及当前油量、花费作为一个节点(st,0,0)入队。
    2 如果队列不空,则对头(u,vol,cost) 出队,并标记该节点油量已扩展,vis[u][vol]=1。
    3 如果 u 正好是目标 ed,则返回花费 cost。
    4 如果当前油量小于邮箱容量,且 u 的油量 vol + 1 未扩展,则将该节点(u,vol+1,cost+price[u]) 入队。
    5 检查 u 所有临界点 v,如果当前油量大于或等于边权 w,且 v 节点的油量 vol - w 未扩展,则将该节点 (v,vol-w,cost) 入队。
    6 转向步骤 2。

    六 代码

    1. package com.platform.modules.alg.alglib.poj3635;
    2. import java.util.PriorityQueue;
    3. public class Poj3635 {
    4. public String output = "";
    5. private final int maxn = 1005;
    6. private final int maxm = 20005;
    7. edge edge[] = new edge[maxm];
    8. int head[] = new int[maxn];
    9. boolean vis[][] = new boolean[maxn][105];
    10. int n;
    11. int m;
    12. int V;
    13. int st;
    14. int ed;
    15. int cnt;
    16. int price[] = new int[maxn];
    17. public Poj3635() {
    18. for (int i = 0; i < edge.length; i++) {
    19. edge[i] = new edge();
    20. }
    21. }
    22. void add(int u, int v, int w) {
    23. edge[cnt].v = v;
    24. edge[cnt].w = w;
    25. edge[cnt].next = head[u];
    26. head[u] = cnt++;
    27. }
    28. int bfs() {
    29. for (int i = 0; i < maxn; i++) {
    30. for (int j = 0; j < 105; j++) {
    31. vis[i][j] = false;
    32. }
    33. }
    34. PriorityQueue Q = new PriorityQueue<>(); // 优先队列
    35. Q.add(new node(st, 0, 0));
    36. while (!Q.isEmpty()) {
    37. node cur = Q.peek();
    38. Q.poll();
    39. int u = cur.u, vol = cur.vol, cost = cur.cost;
    40. vis[u][vol] = true;
    41. if (u == ed) return cost;
    42. if (vol < V && !vis[u][vol + 1])
    43. Q.add(new node(u, vol + 1, cost + price[u]));
    44. for (int i = head[u]; i != -1; i = edge[i].next) {
    45. int v = edge[i].v, w = edge[i].w;
    46. if (vol >= w && !vis[v][vol - w])
    47. Q.add(new node(v, vol - w, cost));
    48. }
    49. }
    50. return -1;
    51. }
    52. public String cal(String input) {
    53. String[] line = input.split("\n");
    54. String[] words = line[0].split(" ");
    55. n = Integer.parseInt(words[0]);
    56. m = Integer.parseInt(words[1]);
    57. String[] pricestr = line[1].split(" ");
    58. for (int i = 0; i < n; i++) {
    59. price[i] = Integer.parseInt(pricestr[i]);
    60. }
    61. int u, v, w;
    62. cnt = 0;
    63. for (int i = 0; i < head.length; i++) {
    64. head[i] = -1;
    65. }
    66. for (int i = 0; i < m; i++) {
    67. String[] edgs = line[2 + i].split(" ");
    68. u = Integer.parseInt(edgs[0]);
    69. v = Integer.parseInt(edgs[1]);
    70. w = Integer.parseInt(edgs[2]);
    71. add(u, v, w);
    72. add(v, u, w);
    73. }
    74. int q = Integer.parseInt(line[2 + m]);
    75. for (int i = 0; i < q; i++) {
    76. String[] querys = line[3 + m + i].split(" ");
    77. V = Integer.parseInt(querys[0]);
    78. st = Integer.parseInt(querys[1]);
    79. ed = Integer.parseInt(querys[2]);
    80. int ans = bfs();
    81. if (ans == -1) output += "impossible";
    82. else {
    83. output += String.valueOf(ans) + "\n";
    84. }
    85. }
    86. return output;
    87. }
    88. }
    89. class edge {
    90. int v;
    91. int w;
    92. int next;
    93. }
    94. class node implements Comparable {
    95. int u;
    96. int vol;
    97. int cost;
    98. node(int u_, int vol_, int cost_) {
    99. u = u_;
    100. vol = vol_;
    101. cost = cost_;
    102. }
    103. @Override
    104. public int compareTo(Object o) {
    105. return this.cost - ((node) o).cost;
    106. }
    107. }

    七测试

     

  • 相关阅读:
    Vue的三种网络请求方式
    [编程思想录]无锁之CAS
    Windows中的用户帐户与组账户
    用 docker 创建 jmeter 容器, 实现性能测试,该如何下手?
    笔记:.NET的框架梳理及相关概念了解(“.NET Core“ “.NET“ “.NET Framework“)
    会员通?会员通!
    Direct3D的初始化
    在浏览器输入url到页面展示出来
    [黑马程序员SpringBoot2]——基础篇2
    计算机网络基础知识1
  • 原文地址:https://blog.csdn.net/chengqiuming/article/details/126443160