• 拆点____ 行车路线


    3255. 行车路线

    小明和小芳出去乡村玩,小明负责开车,小芳来导航。

    小芳将可能的道路分为大道和小道。

    大道比较好走,每走 1 公里小明会增加 1 的疲劳度。

    小道不好走,如果连续走小道,小明的疲劳值会快速增加,连续走 s 公里小明会增加 s^2 的疲劳度。

    例如:有 5 个路口,1 号路口到 2 号路口为小道,2 号路口到 3 号路口为小道,3 号路口到 4 号路口为大道,4 号路口到 5 号路口为小道,相邻路口之间的距离都是 2 公里。

    如果小明从 1 号路口到 5 号路口,则总疲劳值为 (2+2)^2+2+2^2=16+2+4=22。

    现在小芳拿到了地图,请帮助她规划一个开车的路线,使得按这个路线开车小明的疲劳度最小。

    输入格式

    输入的第一行包含两个整数 n,m,分别表示路口的数量和道路的数量。路口由 1 至 n 编号,小明需要开车从 1 号路口到 n 号路口。

    接下来 m 行描述道路,每行包含四个整数 t,a,b,c,表示一条类型为 t,连接 a 与 b 两个路口,长度为 c 公里的双向道路。其中 t 为 0 表示大道,t 为 1 表示小道。

    保证 1 号路口和 n 号路口是连通的。

    输出格式

    输出一个整数,表示最优路线下小明的疲劳度。

    数据范围

    对于 30% 的评测用例,1≤n≤8,1≤m≤10;
    对于另外 20% 的评测用例,不存在小道;
    对于另外 20% 的评测用例,所有的小道不相交;
    对于所有评测用例,1≤n≤500,1≤m≤10^5,1≤a,b≤n,t 是 0 或 1,c≤10^5。
    保证答案不超过 10^6

    输入样例:
    1. 6 7
    2. 1 1 2 3
    3. 1 2 3 2
    4. 0 1 3 30
    5. 0 3 4 20
    6. 0 4 5 30
    7. 1 3 5 6
    8. 1 5 6 1
    输出样例:
    76
    
    样例解释

    从 1 走小道到 2,再走小道到 3,疲劳度为 5^2=25;然后从 3 走大道经过 4 到达 5,疲劳度为 20+30=50;最后从 5 走小道到 6,疲劳度为 1。

    总共为 76。

    因为保证答案不超过10^6, 所以连续小路长度超过1000
    因为点的数据范围为500,所以可以拆点,第二维表示当前连续小路长度 

    1. #include
    2. using namespace std;
    3. const int N = 510, M = 200010, INF = 1e6;
    4. int n, m;
    5. int h[N], e[M], f[M], w[M], ne[M], idx; //f表示道路类型
    6. int dist[N][1010];
    7. bool st[N][1010];
    8. struct Node
    9. {
    10. int x, y, v; //x当前点,y当前连续小路长度,v为dist[x][y]
    11. bool operator< (const Node& t) const
    12. {
    13. return v > t.v; //小根堆(从小到大)
    14. }
    15. };
    16. void add(int t, int a, int b, int c)
    17. {
    18. e[idx] = b, f[idx] = t, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
    19. }
    20. void dijkstra()
    21. {
    22. memset(dist, 0x3f, sizeof dist);
    23. dist[1][0] = 0;
    24. priority_queue heap;
    25. heap.push({1, 0, 0});
    26. while (heap.size())
    27. {
    28. Node t = heap.top();
    29. heap.pop();
    30. if (st[t.x][t.y]) continue; //dijkstra()所有点只遍历一次
    31. st[t.x][t.y] = true;
    32. for (int i = h[t.x]; ~i; i = ne[i])
    33. {
    34. int j = e[i], y = t.y;
    35. if (f[i]) //小路
    36. {
    37. y += w[i]; //小路长度更新
    38. if (y <= 1000) //连续小路长度一定小于1000
    39. {
    40. if (dist[j][y] > t.v - t.y * t.y + y * y)
    41. {
    42. dist[j][y] = t.v - t.y * t.y + y * y;
    43. if (dist[j][y] <= INF)
    44. heap.push({j, y, dist[j][y]});
    45. }
    46. }
    47. }
    48. else
    49. {
    50. if (dist[j][0] > t.v + w[i])
    51. {
    52. dist[j][0] = t.v + w[i];
    53. if (dist[j][0] <= INF)
    54. heap.push({j, 0, dist[j][0]});
    55. }
    56. }
    57. }
    58. }
    59. }
    60. int main()
    61. {
    62. cin >> n >> m;
    63. memset(h, -1, sizeof h);
    64. while (m --)
    65. {
    66. int t, a, b, c;
    67. scanf("%d%d%d%d", &t, &a, &b, &c);
    68. add(t, a, b, c), add(t, b, a, c);
    69. }
    70. dijkstra();
    71. int res = INF;
    72. for (int i = 0; i <= 1000; i ++) res = min(res, dist[n][i]);
    73. //表示最后一段小路的长度为i的前提下,1到n的最短距离
    74. cout << res;
    75. return 0;
    76. }

     

  • 相关阅读:
    vue项目中常见的三种文件类型在线预览实现(pdf/word/excel表格)
    服务 700+ 厂商,接入 4000+游戏,数数科技 C+ 轮再融 1 亿元
    wsl下jdk+wsl调试环境
    [Power Query] 快速计算列
    前端开发流程与技术选型
    Java基础学习——类的自然排序Comparable
    java计算机毕业设计干洗店订单管理系统设计与实现源码+mysql数据库+系统+lw文档+部署
    Spring在业务中常见的使用方式
    js浮点数精度问题详解
    常见的http请求头以及响应头
  • 原文地址:https://blog.csdn.net/Zo_ee/article/details/134518269