poj1723 SOLDIERS

soldiers真乃神题也!

行列显然可以分开处理。

行好办,显然就是一个货仓选址问题,取中位数即可。

列呢??

??????

因为懒得推式子,用不了二分,我决定使用枚举大法!一算复杂度O(n^2),勉强可以卡过。

于是我做好了卡常数的准备,正在实现枚举及求值时,得到了援助:

你把士兵按照x排序,然后把x[i] - i即可转化为行上面的。

我略加思索:排好后是x[1], x[1] + 1, x[i] + 2, ..., x[i] + (i - 1)

那么我事先减去,便是x[1], x[1], x[1], ..., x[1]

妙啊,妙啊!

关于为何排序:使用了一点贪心的思想:如果一个A在B左边,那么排好队之后A也一定在B左边。

然后我抱着试一试的心态,过了样例,一口气AC了!!!


我们学到了什么?

转换:减去i

 

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 using std::sort;
 5 inline void read(int &x) {
 6     x = 0;
 7     bool f = 0;
 8     char c = getchar();
 9     while(c < '0' || c > '9') {
10         if(c == '-') {
11             f = 1;
12         }
13         c = getchar();
14     }
15     while(c <= '9' && c >= '0') {
16         x = (x << 3) + (x << 1) + c - '0';
17         c = getchar();
18     }
19     if(f) x = -x;
20     return;
21 }
22 inline void max(int &a, int b) {
23     if(a < b) a = b;
24     return;
25 }
26 inline void min(int &a, int b) {
27     if(a > b) a = b;
28     return;
29 }
30 inline int ab(int x) {
31     return (x < 0) ? ((~x) + 1) : x;
32 }
33 const int N = 10005, INF = 0x7f7f7f7f;
34 
35 int x[N], y[N], n;
36 
37 int main() {
38     int lx = -INF, sx = INF;
39     int xx, yy;
40     read(n);
41     for(int i = 1; i <= n; i++) {
42         read(x[i]);
43         read(y[i]);
44     }
45 
46     long long ans = 0;
47 
48     ///solve y -> 1
49     sort(y + 1, y + n + 1);
50     int k = y[(n + 1) >> 1];
51     for(int i = 1; i <= n; i++) {
52         ans += ab(y[i] - k);
53     }
54 
55     /// solve x -> []
56     sort(x + 1, x + n + 1);
57     for(int i = 1; i <= n; i++) {
58         x[i] -= (i - 1);
59     }
60     sort(x + 1, x + n + 1);
61     k = x[(n + 1) >> 1];
62     for(int i = 1; i <= n; i++) {
63         ans += ab(x[i] - k);
64     }
65 
66     printf("%lld", ans);
67     return 0;
68 }
AC代码

 

posted @ 2018-05-14 13:50  garage  阅读(81)  评论(0编辑  收藏  举报