#include
<
iostream
>
#include
<
vector
>
#include
<
algorithm
>
using
namespace
std;
int
main() {
vector
<
int
>
times;
int
n, min
=
0
, t, t1, t2;
cin
>>
n;
for
(
int
i
=
0
;i
<
n;i
++
) {
cin
>>
t;
times.push_back(t);
}
sort(times.begin(), times.end());
for
(
int
i
=
times.size()
-
1
; i
>=
3
; i
-=
2
) {
t1
=
times[
1
]
+
times[
0
]
+
times[i]
+
times[
1
];
t2
=
times[i]
+
times[
0
]
+
times[i
-
1
]
+
times[
0
];
if
( t1
<=
t2 ) {
times.pop_back();
times.pop_back();
min
+=
t1;
}
else
{
break
;
}
}
for
(
int
i
=
times.size()
-
1
; i
>
1
; i
--
) {
min
+=
times[i]
+
times[
0
];
times.pop_back();
}
if
(times.size()
==
2
)
min
+=
times[
1
];
else
min
+=
times[
0
];
cout
<<
min
<<
endl;
return
0
;
}
咋看题意,比较单纯的我就以为每次只要用最快的人带另一个人过去对面,然后回来,这样就是最短时间。
但作者人很好,因为他在示例数据里面已经告诉所有像我那样单纯的人,这样的想法是不对的。
然而实在太单纯了,竟然不知道示例数据是如何计算出来的,唯有去看discuss了。
看过了以后知道了,如果有两个人,他们过对面花费的时间都很大,那么把这两个人捆绑一齐送过去,然后再把对面一个走得很快的人回来,这样可能更好。
明白了这一点后,我第一个反应就是DP,谁知道这题的DP是2^100 (n<=100),我知道自己又错了。
后来想了一下,只要总是比较一种情况,迭代到最后就可以了。
假设按耗时从低到高来排序所有人,那么得到序列T0,T1,...,Tn-2,Tn-1
那么到底把两个走得慢的人捆绑到对面,再送一个“快人”回来的优势有多大呢?算一下就好,取哪两个“慢人”好呢?当然是最慢的。
T1(两个“快人”过去) + T0(最快的人回来)+ Tn-1(最慢两人过去) + T1(次快的人回来)
然后就这样把两个最慢的人送过去了,而常规的,用最快的人分别送这两个慢人过去的计算就不说了。 比较一下就知道哪个方案的优势高。
如果对最慢的两个人都失去优势,那么对其他剩下的人也是。

