【每日一题】codeJan与旅行 题解

codeJan与旅行

https://ac.nowcoder.com/acm/contest/56/B

我哭了, 一大早起床本来想做个题后写作业, 结果被这道题搞了几个小时满脑子都是乱的还做不出来, 跑去看了题解

Solution

大致思想其实挺好想的(注意!是大致!) 因为题目保证不会存在 与城市节点重合的情况
我们先处理出 左右两个城市的位置(注意一下边界的处理)
然后很显然的, 我们可以找到从当前位置去到两个距离小的城市进行反复移动
到所枚举城市的距离, 为还需要访问多少个城市, 为到枚举点途径的城市数
, 最终结果就是 , 其中 为所枚举的终点城市
设移动到左边最近城市后枚举为方案1, 移动到右边最近城市后枚举为方案2
比较两个方案的 大小即可
这道题就做完了......吗?
其实没有!
因为会存在两种情况可能更优, 先往左走一个城市, 再往右边最近城市, 此时再做方案2
或者先往右走一个城市, 再往左边最近城市, 此时在做方案1
这里也是看了 聚聚的题解才知道
比如数据
1
3 10 2
1 10 14
答案是42
此时就会出现上面的情况

Code

/*
  autor: Kurisu
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const long long inf = 1e18;
const int N = 1e6 + 5;
const double eps = 1e-10;
const ll mod = 1e9 + 7;
ll sum[N], a[N];

int main() {
  ios::sync_with_stdio(false), cin.tie(nullptr);
  int t;
  cin >> t;
  while (t--) {
    int n, m, p;
    cin >> n >> m >> p;
    int pos = 0;
    for(int i = 1; i <= n; i++) {
      cin >> a[i];
      if(a[i] < p) pos = i;
    }
    ll ans = 1e18;
    for(int i = 1; i < n; i++) { 
      if(i <= pos) { // 往左走
        if(pos - i + 1 > m) continue;
        ll num = m - (pos - i + 1), dist = p - a[i];
        ans = min(ans, dist + num * (a[i + 1] - a[i]));
        if(num > 0 && pos + 1 <= n) { // 先往右走一格, 再往左走
          ans = min(ans, (a[pos + 1] - p) * 2 + dist + (num - 1) * (a[i + 1] - a[i])); 
        }
      } else { // 往右走
        if(i - pos > m) continue;
        ll num = m - (i - pos), dist = a[i] - p;
        ans = min(ans, dist + num * (a[i + 1] - a[i]));
        if(num > 0 && pos >= 1) { // 先左走一格 再往右走
          ans = min(ans, (p - a[pos]) * 2 + dist + (num - 1) * (a[i + 1] - a[i]));
        }
      }
    }
    cout << ans << "\n";
  }
  return 0;
}
Kurisu与牛客的每日一题 文章被收录于专栏

每日一题

全部评论
所以作业写了吗?/xyx
点赞 回复 分享
发布于 2020-05-08 11:32

相关推荐

06-26 15:33
青岛工学院 Java
积极的秋田犬要冲国企:他现在邀请我明天面试
点赞 评论 收藏
分享
头顶尖尖的程序员:我是26届的不太懂,25届不应该是找的正式工作吗?为什么还在找实习?大四还实习的话是为了能转正的的岗位吗
点赞 评论 收藏
分享
xdm怎么说&nbsp;要被拷打了&nbsp;担心是KPI
丹田:面就完了,就当日薪四位数的大佬免费给给你面试。
点赞 评论 收藏
分享
评论
3
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务