题意

大家都是优秀生,这点英文还是看得懂的:点此看题

题解

由于旅行路线成一个环,所以从哪里出发不重要,我们把景点按照

a

i

a_i

ai​ 排序,不妨就从左边最小的出发。基础的旅行费用

c

i

c_i

ci​ 是都要算上的,我们的目的是最小化额外的费用

max

(

0

,

(

a

j

a

i

)

c

j

)

\sum\max(0,(a_j-a_i)-c_j)

∑max(0,(aj​−ai​)−cj​) 。

很明显有一部分的景点是回程(从大到小飞回起点)的时候经过的,这些景点一定没有额外费用。其它景点是来路经过的,费用取决于相邻两个的“间距”(

a

a

a 的差)。最左端和最右端都在来路上。

我们不妨用

d

p

[

i

]

dp[i]

dp[i] 表示来路上经过

i

i

i 时,最小的额外花费是多少。那么假设从

i

i

i 往左数,直到

k

k

k 以内的前驱,到

i

i

i 的额外花费都是 0(这个 k 可以预处理出来),则转移为:

d

p

[

i

]

=

min

{

min

j

=

k

i

1

d

p

[

j

]

,

a

i

+

(

min

j

=

1

k

1

(

d

p

[

j

]

a

j

)

)

c

i

}

dp[i]=\min\bigg\{\min_{j=k}^{i-1} dp[j]~,~a_i+\big(\min_{j=1}^{k-1} (dp[j]-a_j)\big)-c_i\bigg\}

dp[i]=min{j=kmini−1​dp[j] , ai​+(j=1mink−1​(dp[j]−aj​))−ci​}

可以分别建立两棵线段树来优化

D

P

\rm DP

DP 。时间复杂度

Θ

(

n

log

n

)

\Theta(n\log n)

Θ(nlogn) 。

CODE

和上面说的不同,这个是从右到左算的。

  1. #include<set>
  2. #include<queue>
  3. #include<cmath>
  4. #include<vector>
  5. #include<cstdio>
  6. #include<cstring>
  7. #include<iostream>
  8. #include<algorithm>
  9. using namespace std;
  10. #define MAXN 200005
  11. #define ENDL putchar('\n')
  12. #define LL long long
  13. #define DB double
  14. #define lowbit(x) ((-x) & (x))
  15. LL read() {
  16. LL f = 1,x = 0;char s = getchar();
  17. while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
  18. while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
  19. return f * x;
  20. }
  21. int n,m,i,j,s,o,k;
  22. struct it{
  23. int a,c,id;
  24. }p[MAXN];
  25. LL dp[MAXN];
  26. bool cmp(it x,it y) {
  27. if(x.a != y.a) return x.a < y.a;
  28. if(x.id == 1) return 1;
  29. if(y.id == 1) return 0;
  30. return x.c < y.c;
  31. }
  32. int tre1[MAXN<<2],tre2[MAXN<<2],M;
  33. int bing1(int x,int y) {
  34. if(!x || !y) return x+y;
  35. if(dp[x] != dp[y]) return dp[x] < dp[y] ? x:y;
  36. return max(x,y);
  37. }
  38. int bing2(int x,int y) {
  39. if(!x || !y) return x+y;
  40. if(dp[x]+p[x].a != dp[y]+p[y].a) return dp[x]+p[x].a < dp[y]+p[y].a ? x:y;
  41. return max(x,y);
  42. }
  43. void maketree(int n) {M=1;while(M<n+2)M<<=1;}
  44. void addtree(int x,int y) {
  45. int s = M+x;tre1[s] = tre2[s] = y;s >>= 1;
  46. while(s) tre1[s] = bing1(tre1[s<<1],tre1[s<<1|1]),tre2[s] = bing2(tre2[s<<1],tre2[s<<1|1]),s >>= 1;
  47. }
  48. int findtree1(int l,int r) {
  49. int as = 0; if(l > r) return as;
  50. int s = M+l-1,t = M+r+1;
  51. while(s || t) {
  52. if((s>>1) ^ (t>>1)) {
  53. if(!(s & 1)) as = bing1(as,tre1[s^1]);
  54. if(t & 1) as = bing1(as,tre1[t^1]);
  55. }else break;
  56. s >>= 1;t >>= 1;
  57. }return as;
  58. }
  59. int findtree2(int l,int r) {
  60. int as = 0; if(l > r) return as;
  61. int s = M+l-1,t = M+r+1;
  62. while(s || t) {
  63. if((s>>1) ^ (t>>1)) {
  64. if(!(s & 1)) as = bing2(as,tre2[s^1]);
  65. if(t & 1) as = bing2(as,tre2[t^1]);
  66. }else break;
  67. s >>= 1;t >>= 1;
  68. }return as;
  69. }
  70. int rr[MAXN];
  71. int main() {
  72. n = read();
  73. LL ans = 0;
  74. for(int i = 1;i <= n;i ++) {
  75. p[i].a = read();p[i].c = read();
  76. ans += p[i].c;
  77. p[i].id = i;
  78. }
  79. sort(p + 1,p + 1 + n,cmp);
  80. maketree(n);
  81. for(int i = 1;i < n;i ++) {
  82. rr[i] = i;
  83. for(int j = 17;j >= 0;j --) {
  84. if(rr[i]+(1<<j) <= n && p[rr[i]+(1<<j)].a <= p[i].a+p[i].c) rr[i] += (1<<j);
  85. }
  86. }
  87. dp[n] = 0;
  88. addtree(n,n);
  89. for(int i = n-1;i > 0;i --) {
  90. int t1 = findtree1(i+1,rr[i]),t2 = findtree2(rr[i]+1,n);
  91. dp[i] = 1e18;
  92. if(t1) dp[i] = min(dp[i],dp[t1]);
  93. if(t2) dp[i] = min(dp[i],dp[t2] + p[t2].a - (p[i].a+p[i].c));
  94. addtree(i,i);
  95. }
  96. printf("%lld\n",ans + dp[1]);
  97. return 0;
  98. }

Codeforces 1503C Travelling Salesman Problem(Dynamic Programming)的更多相关文章

  1. PAT A1150 Travelling Salesman Problem (25 分)——图的遍历

    The "travelling salesman problem" asks the following question: "Given a list of citie ...

  2. 1150 Travelling Salesman Problem(25 分)

    The "travelling salesman problem" asks the following question: "Given a list of citie ...

  3. hdu 5402 Travelling Salesman Problem(大模拟)

    Problem Description Teacher Mai ,) to the bottom right corner (n,m). He can choose one direction and ...

  4. #C++初学记录(动态规划(dynamic programming)例题1 钞票)

    浅入动态规划 dynamic programming is a method for solving a complex problem by breaking it down into a coll ...

  5. 详解动态规划(Dynamic Programming)& 背包问题

    详解动态规划(Dynamic Programming)& 背包问题 引入 有序号为1~n这n项工作,每项工作在Si时间开始,在Ti时间结束.对于每项工作都可以选择参加与否.如果选择了参与,那么 ...

  6. 笔试算法题(44):简介 - 动态规划(Dynamic Programming)

    议题:动态规划(Dynamic Programming) 分析: DP主要用于解决包含重叠子问题(Overlapping Subproblems)的最优化问题,其基本策略是将原问题分解为相似的子问题, ...

  7. HDU 5402 Travelling Salesman Problem (模拟 有规律)(左上角到右下角路径权值最大,输出路径)

    Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (J ...

  8. 对动态规划(Dynamic Programming)的理解:从穷举开始(转)

    转自:http://janfan.cn/chinese/2015/01/21/dynamic-programming.html 动态规划(Dynamic Programming,以下简称dp)是算法设 ...

  9. hdu 5402 Travelling Salesman Problem (技巧,未写完)

    题意:给一个n*m的矩阵,每个格子中有一个数字,每个格子仅可以走一次,问从(1,1)走到(n,m) 的路径点权之和. 思路: 想了挺久,就是有个问题不能短时间证明,所以不敢下手. 显然只要n和m其中一 ...

随机推荐

  1. 深度学习与CV教程(13) | 目标检测 (SSD,YOLO系列)

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/37 本文地址:http://www.showmeai.tech/article-det ...

  2. 能快速搭建三维场景,这款3D全场景编辑器你还没用过吗?

    今天就给大家分享一个非常好用的老子云3D全场景编辑器,不仅可以基于GIS数据,帮助用户快速搭建3D城市大场景.实现Web端流畅展示. 并且搭建的3D场景可离线开发成一个空间信息直观的.可交互.易于设计 ...

  3. ShardingSphere-proxy-5.0.0分布式哈希取模分片实现(四)

    一.说明 主要是对字符串的字段进行hash取模 二.修改配置文件config-sharding.yaml,并重启服务 # # Licensed to the Apache Software Found ...

  4. Vue回炉重造之如何使用props、emit实现自定义双向绑定

    下面我将使用Vue自带的属性实现简单的双向绑定. 下面的例子就是利用了父组件传给子组件(在子组件定义props属性,在父组件的子组件上绑定属性),子组件传给父组件(在子组件使用$emit()属性定义一 ...

  5. Docker 与 K8S学习笔记(二十五)—— Pod的各种调度策略(上)

    上一篇,我们学习了各种工作负载的使用,工作负载它会自动帮我们完成Pod的调度和部署,但有时我们需要自己定义Pod的调度策略,这个时候该怎么办呢?今天我们就来看一下如何定义Pod调度策略. 一.Node ...

  6. Node.js精进(6)——文件

    文件系统是一种用于向用户提供底层数据访问的机制,同时也是一套实现了数据的存储.分级组织.访问和获取等操作的抽象数据类型. Node.js 中的fs模块就是对文件系统的封装,整合了一套标准 POSIX ...

  7. Linux编辑shell脚本快速启动jar包

    1.上传jar包到服务器 2.创建并编辑start.sh文件 vi start.sh 将下面内容复制到文件中 ps -ef|grep xf-demo |grep -v grep |awk '{prin ...

  8. SpringBoot项目集成Swagger启动报错: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is

    使用的Swagger版本是2.9.2.knife4j版本是2.0.4. SpringBoot 版本是2.6.2将SpringBoot版本回退到2.5.6就可以正常启动

  9. JDBC:获取自增长键值的序号

    1.改变的地方  实践: package com.dgd.test; import java.io.FileInputStream; import java.io.FileNotFoundExcept ...

  10. 万字干货|Java基础面试题(2022版)

    目录 概念常识 Java 语言有哪些特点? JVM.JRE和JDK的关系 什么是字节码? 为什么说 Java 语言是"编译与解释并存"? Oracle JDK 和OpenJDK的区 ...