题目
分析
- 贪心;
- 有一座桥,一次仅能通过两人,通过的条件是持有手电筒,所以手电筒需要有人带回。输出最短的通过时间以及通过过程。
- 过桥有两个最优策略。
策略一
最快的小伙砸(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;
}
本文探讨了经典的过桥问题,提出两种贪心策略来解决该问题,并通过代码实现了解决方案。首先对过桥时间进行排序,然后根据不同人数情况选择最优策略,最终输出最短时间和过桥顺序。
249

被折叠的 条评论
为什么被折叠?



