http://codeforces.com/contest/709
题目大意:给一个一维的坐标轴,上面有n个点,我们刚开始在位置a,问,从a点开始走,走n-1个点所需要的最小路程。
思路:我们知道,如果你一会儿走左一会儿左右,最后访问n-1个点一定只会让距离更长的,所以我们的策略是刚开始全都往一端走,然后访问完n-1个点即可。刚开始我是分类讨论的。。。讨论的要死了。。。不过后来看了一下别人的代码,发现虽然思路是对的,但是过程想麻烦了。 具体看代码吧。
我的乱七八糟的分类讨论
//看看会不会爆int! 或者绝对值问题。 #include <bits/stdc++.h> using namespace std; #define LL long long #define pb push_back #define mk make_pair #define fi first #define se second #define ALL(a) a.begin(), a.end() const int maxn = 100000 + 5; const LL inf = 1e18; int n; LL a; LL x[maxn]; int main(){ cin >> n >> a; LL tmp = a; for (int i = 0; i < n; i++) scanf("%lld", x + i); if (n == 1) {printf("0 "); return 0;} sort(x, x + n); x[n] = inf; int pos = lower_bound(x, x + n, a) - x; LL lb = a - x[0], rb = x[n-1] - a; LL ans = inf; if (pos == 0) ans = min(ans, rb - x[n - 1] + x[n - 2]); else if (pos == 1){ ans = min(rb, lb * 2 + rb - x[n - 1] + x[n - 2]); ans = min(2 * abs(rb - x[n - 1] + x[n - 2]) + lb, ans); } else if (pos == n - 1) { if (x[pos] == a) ans = min(ans, lb - x[1] + x[0]); else { ans = min(lb, rb * 2 + lb - x[1] + x[0]); ans = min(ans, 2 * (lb - x[1] + x[0]) + rb); } } else if (pos == n) ans = min(ans, lb - x[1] + x[0]); else { ans = min(2 * lb + rb - x[n - 1] + x[n - 2], 2 * rb + lb - x[1] + x[0]); ans = min(ans, 2 * (lb - x[1] + x[0]) + rb); ans = min(ans, 2 * (rb - x[n - 1] + x[n - 2]) + lb); } cout << ans << endl; return 0; }
另一种写法,很简便
//看看会不会爆int! 或者绝对值问题。 #include <bits/stdc++.h> using namespace std; #define LL long long #define pb push_back #define mk make_pair #define fi first #define se second #define ALL(a) a.begin(), a.end() const int maxn = 100000 + 5; const LL inf = 1e18; int n; LL a; LL x[maxn]; int main(){ cin >> n >> a; for (int i = 0; i < n; i++) scanf("%lld", x + i); if (n == 1) {printf("0 "); return 0;} sort(x, x + n); x[n] = inf; LL ans = min(abs(x[0] - a), abs(x[n - 2] - a)) + x[n - 2] - x[0]; LL tmp = min(abs(x[1] - a), abs(x[n - 1] - a)) + x[n - 1] - x[1]; cout << min(ans, tmp) << endl; return 0; }