zoukankan      html  css  js  c++  java
  • tc 146 2 BridgeCrossing(n人过桥问题)

    SRM 146 1000BridgeCrossing


    Problem Statement

    A well-known riddle goes like this: Four people are crossing an old bridge. The bridge cannot hold more than two people at once. It is dark, so they can't walk without a flashlight, and they only have one flashlight! Furthermore, the time needed to cross the bridge varies among the people in the group. For instance, let's say that the people take 1, 2, 5 and 10 minutes to cross the bridge. When people walk together, they always walk at the speed of the slowest person. It is impossible to toss the flashlight across the bridge, so one person always has to go back with the flashlight to the others. What is the minimum amount of time needed to get all the people across the bridge?

    In this instance, the answer is 17. Person number 1 and 2 cross the bridge together, spending 2 minutes. Then person 1 goes back with the flashlight, spending an additional one minute. Then person 3 and 4 cross the bridge together, spending 10 minutes. Person 2 goes back with the flashlight (2 min), and person 1 and 2 cross the bridge together (2 min). This yields a total of 2+1+10+2+2 = 17 minutes spent.

    You want to create a computer program to help you solve new instances of this problem. Given an int[] times, where the elements represent the time each person spends on a crossing, your program should return the minimum possible amount of time spent crossing the bridge.

    Definition

    • ClassBridgeCrossing
    • MethodminTime
    • Parametersvector<int>
    • Returnsint
    • Method signatureint minTime(vector<int> times)
    (be sure your method is public)

    Limits

    • Time limit (s)2.000
    • Memory limit (MB)64

    Notes

    • In an optimal solution, exactly two people will be sent across the bridge with the flashlight each time (if possible), and exactly one person will be sent back with the flashlight each time. In other words, in an optimal solution, you will never send more than one person back from the far side at a time, and you will never send less than two people across to the far side each time (when possible).

    Constraints

    • times will have between 1 and 6 elements, inclusive.
    • Each element of times will be between 1 and 100, inclusive.

    Test cases

      1.  
        • times{ 1, 2, 5, 10 }
         
        Returns17
         
        The example from the text.
      2.  
        • times{ 1, 2, 3, 4, 5 }
         
        Returns16
         
        One solution is: 1 and 2 cross together (2min), 1 goes back (1min), 4 and 5 cross together (5min), 2 goes back (2min), 1 and 3 cross together (3min), 1 goes back (1min), 1 and 2 cross together (2min). This yields a total of 2 + 1 + 5 + 2 + 3 + 1 + 2 = 16 minutes spent.
      3.  
        • times{ 100 }
         
        Returns100
         
        Only one person crosses the bridge once.
      4.  
        • times{ 1, 2, 3, 50, 99, 100 }
         
        Returns162
          1 #include <cstdio>
          2 #include <cmath>
          3 #include <cstring>
          4 #include <ctime>
          5 #include <iostream>
          6 #include <algorithm>
          7 #include <set>
          8 #include <vector>
          9 #include <sstream>
         10 #include <typeinfo>
         11 #include <fstream>
         12 
         13 using namespace std;
         14 int ti[2000] , tot = 0 ;
         15 int a[2][1000] ;
         16 class BridgeCrossing {
         17     public:
         18     int minTime(vector<int> tim) {
         19         tot = 1 ;
         20         for (int i : tim) ti[tot ++] = i ; tot -- ;
         21         sort (ti + 1 , ti + tot + 1) ;
         22        // printf ("tot = %d
        " , tot ) ;
         23        // for (int i = 1 ; i <= tot ; i ++) printf ("%d " , ti[i]) ; puts ("") ;
         24         if (tot == 1) return ti[1] ;
         25         if (tot == 2) return ti[2] ;
         26         int sum = ti[2] ;
         27         for (int i = tot ; i >= 3 ; i -= 2) {
         28             if (i == 3) {
         29                 sum += ti[1] + ti[3] ;
         30             }
         31             else {
         32                 if (ti[1] + ti[i - 1] < 2 * ti[2]) sum += ti[1] + ti[i] + ti[1] + ti[i - 1] ;
         33                 else sum += ti[1] + ti[i] + ti[2] + ti[2] ;
         34             }
         35         }
         36         return sum ;
         37     }
         38 };
         39 
         40 // CUT begin
         41 ifstream data("BridgeCrossing.sample");
         42 
         43 string next_line() {
         44     string s;
         45     getline(data, s);
         46     return s;
         47 }
         48 
         49 template <typename T> void from_stream(T &t) {
         50     stringstream ss(next_line());
         51     ss >> t;
         52 }
         53 
         54 void from_stream(string &s) {
         55     s = next_line();
         56 }
         57 
         58 template <typename T> void from_stream(vector<T> &ts) {
         59     int len;
         60     from_stream(len);
         61     ts.clear();
         62     for (int i = 0; i < len; ++i) {
         63         T t;
         64         from_stream(t);
         65         ts.push_back(t);
         66     }
         67 }
         68 
         69 template <typename T>
         70 string to_string(T t) {
         71     stringstream s;
         72     s << t;
         73     return s.str();
         74 }
         75 
         76 string to_string(string t) {
         77     return """ + t + """;
         78 }
         79 
         80 bool do_test(vector<int> times, int __expected) {
         81     time_t startClock = clock();
         82     BridgeCrossing *instance = new BridgeCrossing();
         83     int __result = instance->minTime(times);
         84     double elapsed = (double)(clock() - startClock) / CLOCKS_PER_SEC;
         85     delete instance;
         86 
         87     if (__result == __expected) {
         88         cout << "PASSED!" << " (" << elapsed << " seconds)" << endl;
         89         return true;
         90     }
         91     else {
         92         cout << "FAILED!" << " (" << elapsed << " seconds)" << endl;
         93         cout << "           Expected: " << to_string(__expected) << endl;
         94         cout << "           Received: " << to_string(__result) << endl;
         95         return false;
         96     }
         97 }
         98 
         99 int run_test(bool mainProcess, const set<int> &case_set, const string command) {
        100     int cases = 0, passed = 0;
        101     while (true) {
        102         if (next_line().find("--") != 0)
        103             break;
        104         vector<int> times;
        105         from_stream(times);
        106         next_line();
        107         int __answer;
        108         from_stream(__answer);
        109 
        110         cases++;
        111         if (case_set.size() > 0 && case_set.find(cases - 1) == case_set.end())
        112             continue;
        113 
        114         cout << "  Testcase #" << cases - 1 << " ... ";
        115         if ( do_test(times, __answer)) {
        116             passed++;
        117         }
        118     }
        119     if (mainProcess) {
        120         cout << endl << "Passed : " << passed << "/" << cases << " cases" << endl;
        121         int T = time(NULL) - 1433940589;
        122         double PT = T / 60.0, TT = 75.0;
        123         cout << "Time   : " << T / 60 << " minutes " << T % 60 << " secs" << endl;
        124         cout << "Score  : " << 1000 * (0.3 + (0.7 * TT * TT) / (10.0 * PT * PT + TT * TT)) << " points" << endl;
        125     }
        126     return 0;
        127 }
        128 
        129 int main(int argc, char *argv[]) {
        130     cout.setf(ios::fixed, ios::floatfield);
        131     cout.precision(2);
        132     set<int> cases;
        133     bool mainProcess = true;
        134     for (int i = 1; i < argc; ++i) {
        135         if ( string(argv[i]) == "-") {
        136             mainProcess = false;
        137         } else {
        138             cases.insert(atoi(argv[i]));
        139         }
        140     }
        141     if (mainProcess) {
        142         cout << "BridgeCrossing (1000 Points)" << endl << endl;
        143     }
        144     return run_test(mainProcess, cases, argv[0]);
        145 }
        146 // CUT end
        View Code

        这个问题大家都很熟悉吧,晚上有5个人过河,只有一盏灯,,他们每个人的过河时间为1,2,3,6,18(另一组人1,10,10,10,10)。每次最多两个人过河(过河必须有一个人带着灯),且过河的时间按走得慢的那个人算,求5个人过河所需的最少时间?

        当然这个问题转到程序里自然是变成了n个人过河喽。

        如果你把上面得数据跑了一遍的话,得到29(另一组43)的话。那么心里大概就有最佳方案的笼统概念了:

        现在令n个人走过的时间分别为a1,a2,a3,a4,a5,……an;(从小到大)

        那么一开始肯定先是1,2过河。

        接着考虑花时间最多的那两个人(必须考虑他们,这点很重要),我们怎么送他们呢?

        第一种方案:

          1回来了,让1把n送过去,然后1回来,再让1把n-1送过去:a1 + an + a1 + a(n-1) ;

        第二种方案:

          1回来了,让n,n-1过河,然后2回来,再1,2过河: a1 + an + a2 + a2 ;

        (如果觉得叙述方案时有奇怪的地方,请见怪不怪,总之是为了让每轮送两人,并且每轮结束时保证1,2都在对岸)

        所以这两种方案进行选择时,只要比较:a1 + a(n-1) 和 2× a2 中较小的即可。

        。。。大概就是这样,因为每次送两人,所以总人数为奇数时,还有点细节要考虑。

  • 相关阅读:
    20165222第八周课上补做
    20165222—第八周学习
    20165222《Java程序设计》——实验二 面向对象程序设计
    20165222 结对编程学习
    20165222 第七周学习总结
    20165222 第六周学习总结
    20165222 实验一java开发环境的熟悉
    20165222 第五周学习总结
    JSP
    Servlet
  • 原文地址:https://www.cnblogs.com/get-an-AC-everyday/p/4569146.html
Copyright © 2011-2022 走看看