第五题:T5推箱子
标签:排序、数学、思维
题意:给定 t t t组数据,每组数据给定长度为 n n n的字符串, @ @ @表示箱子, _ \_ _表示空格,求把箱子都推到一起(即两两箱子之间没有空格),最少移动次数。
题解:我们稍微把题意变下,给定 n n n个点在 x x x轴上的的坐标,求把这些点移到同一个位置的最少移动次数。
举个例子(坐标): 3 5 8 10 3 \ 5 \ 8 \ 10 3 5 8 10
如果把这些点都移到 2 2 2的坐标,移动次数为: 1 + 3 + 6 + 8 = 18 1+3+6+8=18 1+3+6+8=18
如果把这些点都移到 3 3 3的坐标,移动次数为: 0 + 2 + 5 + 7 = 14 0+2+5+7=14 0+2+5+7=14
如果把这些点都移到 5 5 5的坐标,移动次数为: 2 + 0 + 3 + 5 = 10 2+0+3+5=10 2+0+3+5=10
如果把这些点都移到 6 6 6的坐标,移动次数为: 3 + 1 + 2 + 4 = 10 3+1+2+4=10 3+1+2+4=10
如果把这些点都移到 8 8 8的坐标,移动次数为: 5 + 3 + 0 + 2 = 10 5+3+0+2=10 5+3+0+2=10
会发现把点移到这些点中最中间那个点,移动次数最少,推箱子问题同理,只不过得去考虑每个箱子会占一个位置,在中间位置( k k k)左边的第一个箱子推到 k − 1 k-1 k−1的位置,其他的同理,即对于第 i i i 个箱子来说,需要移动的距离为 a[k] - a[i] - (k-i)(i<k);在中间位置右边的第 i i i个箱子,同理,需要移动的距离为 a[i] - a[k] - (i-k)(i>k)。
代码:
#include <bits/stdc++.h>
using namespace std;typedef long long ll;
string s;
ll a[1000005];int main() {ll t, n;cin >> t;while (t--) {cin >> n >> s;ll c = 0, ans = 0;for (int i = 0; i < n; i++) {if (s[i] == '@') a[++c] = i;}sort(a + 1, a + 1 + c);ll k = (c + 1) / 2;for (int i = 1; i <= c; i++) {if (i < k) ans += (a[k] - a[i] - (k - i));else ans += (a[i] - a[k] - (i - k));}cout << ans << endl;}return 0;
}