zoukankan      html  css  js  c++  java
  • Wannafly挑战赛7 B

    题目描述 

    codeJan 非常喜欢旅行。现在有 n 个城市排在一条线上,并且 codeJan 的位置不和任何一个城市的位置重叠。
    codeJan 想要游览 m 个城市,同时因为时间是不断变化的,游览一个城市多次也是允许的,但是不能永远待在一个城市,否则那样太无聊了。给出这些城市的位置,codeJan 想要知道游览 m 个城市至少需要走多少米?

    输入描述:

    第一行是一个T≤20代表测试组数。
    每组第一行是三个正整数n,m,p,分别代表城市数量、codeJan想要浏览的城市数量和codeJan当前的位置(单位为米)。
    第二行包含n个正整数pos[i]表示第i个城市的位置,单位为米。
    输入保证pos[i]<pos[i+1](i∈[1,n−1]),并且p ≠ pos[i](i∈[1,n])。

    输出描述:

    对于每组输入数据输出一个正整数表示 codeJan 至少需要走的距离。
    示例1

    输入

    3 
    2 2 2 
    1 3 
    2 2 1 
    2 3 
    4 3 4 
    1 3 5 6

    输出

    3
    2
    3

    说明

    对于第一个样例的坐标最优移动顺序可以是:2→3→1,移动距离一共是3。
    对于第二个样例的坐标最优移动顺序可以是:1→2→3,移动距离一共是2。
    对于第三个样例的坐标最优移动顺序可以是:4→5→6→5,移动距离一共是3。

    备注:

    2≤n≤105,1≤m≤105 ,1≤p,pos[i]≤109。

    题解

    想法题。

    最优答案来自于以下几种情况,取个最小值即可。

    往右走,走到某点后在两点之间徘徊
    往左走, 走到某点后在两点之间徘徊
    往左一步,再往右走,走到某点后在两点之间徘徊
    往右一步,在往左走,走到某点后在两点之间徘徊
    在$p$左右两个城市之间徘徊

    #include <bits/stdc++.h>
    using namespace std;
    
    
    const int maxn = 1000000 + 10;
    int T, n, m;
    long long p;
    long long a[maxn];
    
    int main() {
      scanf("%d", &T);
      while(T --) {
        long long ans = 1e18;
        scanf("%d%d%lld", &n, &m, &p);
        for(int i = 1; i <= n; i ++) {
          scanf("%lld", &a[i]);
        }
        n ++;
        a[n] = p;
        sort(a + 1, a + n + 1);
        int location;
        for(int i = 1; i <= n; i ++) {
          if(a[i] == p) location = i;
        }
        
        if(location > 1) {
          long long sum = 0;
          int num = 0;
          for(int i = location - 1; i >= 1; i --) {
            long long dis = a[i + 1] - a[i];
            sum = sum + dis;
            num ++;
            if(num > m) break;
            if(i != location - 1) {
              ans = min(ans, sum + 1LL * dis * (m - num));
            }
          }
        }
        
        if(location < n) {
          long long sum = 0;
          int num = 0;
          for(int i = location + 1; i <= n; i ++) {
            long long dis = a[i] - a[i - 1];
            sum = sum + dis;
            num ++;
            if(num > m) break;
            if(i != location + 1) {
              ans = min(ans, sum + 1LL * dis * (m - num));
            }
          }
        }
        
        if(location > 1 && location < n) {
          ans = min(ans, min(a[location] - a[location - 1], a[location + 1] - a[location]) + 1LL * (m - 1) * (a[location + 1] - a[location - 1]));
          
          long long sum = (a[location + 1] - a[location]) * 2;
          int num = 1;
          for(int i = location - 1; i >= 1; i --) {
            long long dis = a[i + 1] - a[i];
            sum = sum + dis;
            num ++;
            if(num > m) break;
            if(i != location - 1) {
              ans = min(ans, sum + 1LL * dis * (m - num));
            }
          }
          
          
          sum = (a[location] - a[location - 1]) * 2;
          num = 1;
          for(int i = location + 1; i <= n; i ++) {
            long long dis = a[i] - a[i - 1];
            sum = sum + dis;
            num ++;
            if(num > m) break;
            if(i != location + 1) {
              ans = min(ans, sum + 1LL * dis * (m - num));
            }
          }
          
        }
        
        printf("%lld
    ", ans);
      }
      return 0;
    }
    
  • 相关阅读:
    linux编程:删除文件夹下的空文件
    设置vim的显示颜色
    LVM的实现流程
    LVM(逻辑卷管理器)原理
    Ext2文件的访问与日志文件系统
    Linux系统的Ext2文件系统
    linux 磁盘分区的理解
    postgresql在Linux下的安装
    内存泄漏工具VLD
    关于 正交投影 与 透视投影
  • 原文地址:https://www.cnblogs.com/zufezzt/p/8213571.html
Copyright © 2011-2022 走看看