时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
codeJan 非常喜欢旅行。现在有 n 个城市排在一条线上,并且 codeJan 的位置不和任何一个城市的位置重叠。
codeJan 想要游览 m 个城市,同时因为时间是不断变化的,游览一个城市多次也是允许的,但是不能永远待在一个城市,否则那样太无聊了。给出这些城市的位置,codeJan 想要知道游览 m 个城市至少需要走多少米?
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。
解题思路:先找出当前点的左右两个城市,已知最后状态必然要么是恰好走到一个点要么就是在两个点之间来回走,所以枚举在那两个点之间来回即可
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>
using namespace std;
#define LL long long
const LL INF = 0x3f3f3f3f3f3f3f3f;
LL x[100009], p;
int n, m;
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d%d%lld", &n, &m, &p);
for (int i = 1; i <= n; i++) scanf("%lld", &x[i]);
int k = upper_bound(x + 1, x + 1 + n, p) - x;
LL ans = INF, ans1 = 0, ans2 = 0;
int id1 = -1, id2 = -1;
if (k == n + 1) ans1 += p - x[n], id1 = n;
else if (k == 1) ans2 += x[1] - p, id2 = 1;
else
{
ans2 = x[k] - p, id2 = k;
id1 = k - 1, ans1 = p - x[k - 1];
}
if (id1 != -1)
{
for (int i = 1; i <= id1; i++)
{
if (id1 - i + 1 > m || i == n) continue;
LL dis = x[id1] - x[i];
int tmp = id1 - i + 1;
dis += 1LL * (x[i + 1] - x[i])*(m - tmp);
ans = min(ans, ans1 + dis);
if (id2 != -1 && tmp - 1 <= m) ans = min(ans, ans2 + x[id2] - x[i] + 1LL * (x[i + 1] - x[i])*(m - tmp - 1));
}
}
if (id2 != -1)
{
for (int i = id2; i <= n; i++)
{
if (i - id2 + 1 > m || i == 1) continue;
LL dis = x[i] - x[id2];
int tmp = i - id2 + 1;
dis += 1LL * (x[i] - x[i - 1])*(m - tmp);
ans = min(ans, ans2 + dis);
if (id1 != -1 && tmp - 1 <= m) ans = min(ans, ans1 + x[i] - x[id1] + 1LL * (x[i] - x[i - 1])*(m - tmp - 1));
}
}
printf("%lld\n", ans);
}
return 0;
}