过桥(bridge.cpp)
【问题描述】 有n个人希望在晚上通过一座桥。在任何时刻,最多只能有两个人在桥上,而且必须要带着电筒才能过桥。一共只有一个手电筒,所以必须安排某种顺序,使得手电筒可以被带回去让更多的人过桥(手电筒必须由人带回,不可以从对岸扔过去)。 每个人都有不同的过桥时间,两个人一起过桥所花的时间等于其中较慢的一个。你的任务是要找出能在最短时间内使所有人都过桥的方案。
【输入格式】 输入第一行只有一个整数,代表测试点的数量。接下来有一个空行。相邻两组数据之间也有一个空行。 每组数据的第一行有一个整数n,接下来有n行,每一行给出一个人的过桥时间(单位:秒)。人数不超过1000,每个人的过桥时间不超过100秒。
【输出格式】 对于每组数据,输出所有人过桥的总时间。
【时限,空间要求】 1秒,256M。
【输入输出样例】
bridge .in
bridge .out
1 4 1 2 5 10
17
//
// 首先将所有过桥时间排序,以下为获得最小过桥时间的算法:
// (1)过桥总人数为 1,该人的过桥时间即为最短过桥时间。
// (2)过桥总人数为 2,过桥时间较大的人的过桥时间即为最短过桥时间。
// (3)过桥总人数为 3,假设为A,B,C,则(AB),(A),(AC)策略和 (AC),(A),(AB)策略
// 的时间相同,3人过桥时间之和为最短时间。
// (4)过桥总人数大于3,假设最前面为A,B两人,最后为Y,Z两人,有两种策略:(AB),(A),(YZ),
// (B),(AB)和(AZ),(A),(AY),(A),(AB)。比较两种策略那种过桥时间少就选那种,然后
// 将总人数减去 2,若总人数仍大于 3,继续该步骤直到剩下需要过桥的人数小于等于 3。可用递归或直接迭代实现。
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
#define MAXSIZE (1000 + 1)
int shortest_time(int time[], int capacity)
{
if (capacity == 1)
return time[0];
if (capacity == 2)
return time[1];
if (capacity == 3)
return time[0] + time[1] + time[2];
if (2 * time[1] < (time[0] + time[capacity - 2]))
return time[0] + 2 * time[1] + time[capacity - 1] +
shortest_time(time, capacity - 2);
else
return 2 * time[0] + time[capacity - 2] + time[capacity - 1] +
shortest_time(time, capacity - 2);
}
void bridge(int time[], int capacity)
{
if (capacity == 1)
{
cout << time[0] << "\n";
return;
}
if (capacity == 2)
{
cout << time[0] << " " << time[1] << "\n";
return;
}
if (capacity == 3)
{
cout << time[0] << " " << time[2] << "\n";
cout << time[0] << "\n";
cout << time[0] << " " << time[1] << "\n";
return;
}
if (2 * time[1] < (time[0] + time[capacity - 2]))
{
cout << time[0] << " " << time[1] << "\n";
cout << time[0] << "\n";
cout << time[capacity - 2] << " " << time[capacity - 1] << "\n";
cout << time[1] << "\n";
}
else
{
cout << time[0] << " " << time[capacity - 1] << "\n";
cout << time[0] << "\n";
cout << time[0] << " " << time[capacity - 2] << "\n";
cout << time[0] << "\n";
}
bridge(time, capacity - 2);
}
int main(int ac, char *av[])
{
freopen("bridge.in","r",stdin);
freopen("bridge.out","w",stdout);
int cases;
int time[MAXSIZE];
int capacity, index;
cin >> cases;
while (cases--)
{
// 总人数。
cin >> capacity;
// 读取每个人的过桥时间。
index = 0;
while (index < capacity)
cin >> time[index++];
// 将用时数组予以排序。
sort(time, time + capacity);
// 计算最短过桥时间,输出过桥顺序。
cout << shortest_time(time, capacity) << endl;
//bridge(time, capacity);
//if (cases)
//cout << endl;
}
fclose(stdin);
fclose(stdout);
return 0;
}