NYOJ 47 过河问题

来源:互联网 发布:it项目经理 编辑:程序博客网 时间:2024/06/05 11:50

       

过河问题

时间限制:1000 ms  |  内存限制:65535 KB
难度:5
描述

在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,N个人一共只带了一只手电筒,而桥窄得只够让两个人同时过。如果各自单独过桥的话,N人所需要的时间已知;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,如何设计一个方案,让这N人尽快过桥。 

输入
第一行是一个整数T(1<=T<=20)表示测试数据的组数
每组测试数据的第一行是一个整数N(1<=N<=1000)表示共有N个人要过河
每组测试数据的第二行是N个整数Si,表示此人过河所需要花时间。(0<Si<=100)
输出
输出所有人都过河需要用的最少时间
样例输入
141 2 5 10
样例输出
17

       我们知道,当小于4个人的时候,很容易想明白,当n>=4的时候,一开始考虑贪心算法,确实有点没有头绪,但想到贪心,应该从局部最优到全局最优出发,我们知道,当4个人的时候,我们把a[1]`a[4]递增排序,有两种情况:

                 第一种:a[1]+a[4],a[1]回来,a[1]+a[3],a[1]回来,a[1]+a[2],所用时间a[4]+a[1]+a[3]+a[1]+a[2]

                 第二种:a[1]+a[2],a[1]回来,a[3]+a[4],a[2]回来,a[1]+a[2],所用时间a[2]+a[1]+a[4]+a[2]+a[2]

       这时候我们我们应该发现两个问题,这两种情况差值(a[1]+a[3])-(a[2]+a[2])需要再做比较,第二,如果推广到n维,我们要发现这里面的一些共性,两种路径最后都是送走了a[1]+a[2],换句话说,只是送走a[3]和a[4]的时候出现比较情况,如果推广到n维,a[n]的时间是一定要花费的,那么如果第二种情况最优的话,我们可以带走一个次大值,继而我们判断贪心过程就是在n>=4的时候,每次a[1]、a[2]和最大值和次大值的贪心过程。只是如何判断只有这两种情况中存在最优,需要自行脑补一下……

#include<cstdio>  #include<cstring>  #include<string>  #include<vector>  #include<stack>  #include<bitset>  #include<cstdlib>  #include<cmath>  #include<set>  #include<list>  #include<deque>  #include<map>  #include<queue>  #include<algorithm>  #include<iostream>  using namespace std;int t[1005];bool cmp(int a, int b) {return a < b;}int times;void T(int num) {if (num == 1) {times += t[1];return;}if (num == 2) {times += t[2];return;}if (num == 3) {times = times + t[1] + t[2] + t[3];return;}if (num >= 4) {int a = t[num] + t[1] + t[num - 1] + t[1];int b = t[2] + t[1] + t[num] + t[2];times = times +(a < b ? a : b);T(num - 2);}}int main() {int N;int n;cin >> N;while (N--) {times = 0;cin >> n;memset(t, 0, sizeof(t));for (int i = 1; i <= n; i++)cin >> t[i];sort(t+1, t+n+1, cmp);T(n);cout << times << endl;}return 0; }