题目
分析
- 贪心;
- 有一座桥,一次仅能通过两人,通过的条件是持有手电筒,所以手电筒需要有人带回。输出最短的通过时间以及通过过程。
- 过桥有两个最优策略。
策略一
最快的小伙砸(a
)把左岸最慢的小伙砸(z
)带到右岸再回来,再把次慢的小伙砸(y
)带过去再回来,其时间为z+a+y+a
;
策略二
最快的小伙砸和次快的小伙砸(b
)到对岸,最快的小伙砸把手电筒带回来,最慢和次慢的到对岸,次快的小伙砸把手电筒带回来,其时间为b+a+y+b
;
其取舍只需比较z+a+y+a
和b+a+y+b
孰大孰小即可。
思路
- 排序输入的时间;
- 分类讨论
n = 1, 2, 3
和n > 3
的情况,因为n不足4时不需要四次过桥,也就是不符合上述讨论的策略,但不足4的情况也易解。 - 对于
n > 3
的情况只需比较一下策略一和策略二的时长,便可得出要采用哪一策略。 - 因为过程要在时长后输出,所以需要滚两次,第一次得到时长,第二次输出过程。
代码
#include <cstdio>
#include <algorithm>
using namespace std;
int main()
{
int c, n, t[1005], s, i;
scanf("%d", &c);
while (c--) {
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%d", &t[i]);
sort(t, t+n);
s = 0;
while (n) {
if (n == 1) { s += t[0]; break; }
if (n == 2) { s += t[1]; break; }
if (n == 3) { s += t[1]+t[0]+t[2]; break; }
if (t[n-1] + t[0] + t[n-2] + t[0] < t[1] + t[0] + t[n-1] + t[1])
s += t[n-1] + t[0] + t[n-2] + t[0];
else
s += t[1] + t[0] + t[n-1] + t[1];
n -= 2;
}
printf("%d\n", s);
n = i;
while (n) {
if (n == 1) { printf("%d\n", t[0]); break; }
if (n == 2) { printf("%d %d\n", t[0], t[1]); break; }
if (n == 3) { printf("%d %d\n%d\n%d %d\n", t[0], t[2], t[0], t[0], t[1]); break; }
if (t[n-1] + t[0] + t[n-2] + t[0] < t[1] + t[0] + t[n-1] + t[1])
printf("%d %d\n%d\n%d %d\n%d\n",t[0], t[n-1], t[0], t[0], t[n-2], t[0]);
else
printf("%d %d\n%d\n%d %d\n%d\n", t[0], t[1], t[0], t[n-2], t[n-1], t[1]);
n -= 2;
}
if (c) printf("\n");
}
return 0;
}