Wannafly挑战赛7 B - codeJan与旅行
题目描述
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。
题解
想法题。
最优答案来自于以下几种情况,取个最小值即可。
往右走,走到某点后在两点之间徘徊
往左走, 走到某点后在两点之间徘徊
往左一步,再往右走,走到某点后在两点之间徘徊
往右一步,在往左走,走到某点后在两点之间徘徊
在$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\n", ans); } return 0; }