Topcoder BridgeCrossing – SRM 146 Div 2


https://www.topcoder.com/community/competitive-programming/tutorials/how-to-find-a-solution/
A group of people is 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. 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?

There are at most 6 people.

Problem hints:
  • First look at the constraints – there are at most ONLY 6 people! It’s enough for generating all possible permutations, sets etc.
  • There are different possible ways to pass the people from one side to another and you need to find the best one.


This is of course a problem solved with a backtracking: at the beginning choose any 2 people to pass the bridge first, and after that at each step try to pass any of those that have been left on the start side. From all these passages select the one that needs the smallest amount of time. Note that among persons that have passed over the bridge, the one having the greatest speed should return (it’s better than returning one having a lower speed). This fact makes the code much easier to implement. After having realized these things – just code the solution. There may be others – but you will lose more time to find another than to code this one.

https://github.com/irpap/TopCoder/blob/master/BridgeCrossing/src/BridgeCrossing.java
    public int minTime(int[] times) {
        LinkedList<Integer> sideA = new LinkedList<Integer>();
        for (int t : times) sideA.add(t);
        return movePeople(sideA, new LinkedList<Integer>(), true);
    }

    /**
     * returns the min time to move the people from sideA to sideB
     */
    int movePeople(List<Integer> sideA, List<Integer> sideB, boolean torchIsAtSideA) {
        int minTime = Integer.MAX_VALUE;

        if (torchIsAtSideA) {
            if (sideA.isEmpty()) return 0;
            if (sideA.size() == 1) return sideA.get(0);

            for (int i = 0; i < sideA.size(); i++) {
                for (int j = i + 1; j < sideA.size(); j++) {
                    Integer person1 = sideA.get(i);
                    Integer person2 = sideA.get(j);

                    move(person1, sideA, sideB);
                    move(person2, sideA, sideB);

                    minTime = min(minTime, max(person1, person2) + movePeople(sideA, sideB, !torchIsAtSideA));

                    move(person1, sideB, sideA);
                    move(person2, sideB, sideA);
                }
            }
        } else {
            if (sideB.isEmpty() || sideA.isEmpty()) return 0;
            for (int i = 0; i < sideB.size(); i++) {
                Integer personToMove = sideB.get(i);

                move(personToMove, sideB, sideA);

                minTime = min(minTime, personToMove + movePeople(sideA, sideB, !torchIsAtSideA));

                move(personToMove, sideA, sideB);
            }
        }
        return minTime;
    }

    private void move(Integer person, List<Integer> from, List<Integer> to) {
        from.remove(person);
        to.add(person);
    }
X.
https://github.com/kmather73/TopCoder/blob/master/SRM-146-DIV-2/BridgeCrossing.cpp
public int minTime(int[] times) {
if (times.length==1) {
return times[0];
}
Arrays.sort(times);
int total=0;
int rest=times.length;
while (rest>3) {
total+=Math.min(times[0]*2+times[rest-2]+times[rest-1], times[0]+times[1]*2+times[rest-1]);
rest-=2;
}
if (rest==3) {
return total+times[0]+times[1]+times[2];
}
else if (rest==2) {
return total+times[1];
}
return -1;
}

https://sites.google.com/site/topcodingsolutions/srm/div2/146/1000
In order to minimize the time it takes for everyone to cross, we'll want to use the following strategy:
  • Group the slowest people together. If the slowest two people take 5 and 10 minutes respectively, then the trip will take 10 minutes, but there is no faster way to get the slowest person across. By sending the second slowest with the slowest, the second slowest person gets across "for free".
  • Utilize the fastest person in situations where we're just bringing the flashlight back and forth.
The algorithm looks like this:
Repeat until side 1 is empty:
  1. Send the two fastest people (person 1 and person 2) from side 1 to side 2.
  2. Send the fastest (person 1) from side 2 back to side 1.
  3. Send the two slowest people from side 1 to side 2.
  4. Send the fastest person on side 2 (person 2) from side 2 back to side 1.
Once you have the algorithm, the main method is pretty straight forward. I created a method sendOver() to abstract the details of moving people from one side to another.
The sendOver() method takes as parameters the number of people to send (1 or 2), whether we want to send the fastest or slowest people (fastest = true|false), the source side, and the destination side.
Lines 41-45 and 53-58 are a little tricky. Basically, if we're sending the fastest people over, then I'll set currentMax to a high number, and then update it whenever I find something smaller. If I'm looking for slow people, then I set it to a low number, and update it whenever I find something larger. I could have picked a better name than currentMax, since often it will actually be a minimum.


Line 115 might also be confusing. We'll reach this line either once or twice depending on the value of numToSend. The first time, eTime will equal 0, so it will get set to currentMax, the time it took for the first person to cross the bridge. The second time, it will either keep it's value, or get set to the new person's time, depending on who is slower.

015:     /*
016:     Use two hash sets to hold the people that are on
017:     the starting side (side1) and the finish (side2)
018:      */
019:     private final Set side1 = new HashSet();
020: 
021:     private final Set side2 = new HashSet();
022: 
023:     /*
024:     Move people from the "fromSide" set to the "toSide" set.
025:     numToSend - indicates the number of people moving across together.  It
026:     must be either 1 or 2.
027:     fastest - indicates whether we want the fastest people (true), or the
028:     slowest (false) to go across.
029:     Returns the amount of time it will take to move the people across.
030:      */
031:     private static int sendOver(int numToSend, boolean fastest,
032:                                 Set fromSide, Set toSide) {
033: 
034:         int eTime = 0;
035:         int currentMax;
036: 
037:         // Loop either 1 or 2 times, depending on the number being asked to
038:         // send.
039:         for (int n = 0; n < numToSend; n++) {
040: 
041:             if (fastest) {
042:                 currentMax = Integer.MAX_VALUE;
043:             } else {
044:                 currentMax = 0;
045:             }
046: 
047:             /*
048:             If we're looking for the fastest person (fastest = true),
049:             then look for values that are below currentMax.
050:             If we're looking for the slowest person (fastest = false),
051:             then look for values that are above currentMax.
052:              */
053:             for (int i : fromSide) {
054:                 if ((fastest && (i < currentMax)) ||
055:                         (!fastest && (i > currentMax))) {
056:                     currentMax = i;
057:                 }
058:             }
059: 
060:             /*
061:             We've found either the fastest or slowest.  Remove them from the
062:             from side and add them to the to side.
063:             Set eTime to either eTime (if this is the first time through the
064:             loop) or the greater of eTime and currentMax if we've been
065:             through the loop before.  The effect is that eTime will contain the
066:             slower person's time.
067:              */
068:             fromSide.remove(currentMax);
069:             toSide.add(currentMax);
070:             eTime = Math.max(eTime, currentMax);
071:         }
072: 
073:         // Return the slower person's time.  (Just the time if numToSend = 1)
074:         return eTime;
075:     }
076: 
077:     public int minTime(int[] times) {
078: 
079:         int eTime = 0;  // Holds the elapsed time.  The return value.
080: 
081:         // Put all the people onto the starting side
082:         for (int i = 0; i < times.length; i++) {
083:             side1.add(times[i]);
084:         }
085: 
086:         /*
087:         Send the two fastest from side1 to side2.
088:         Check to make sure there are more than 1 people on side 1.
089:         If there is only one person on side1, then just send that one.
090:         */
091:         eTime += sendOver((side1.size() >= 2) ? 2 : 1, true, side1, side2);
092: 
093:         // When side1 no longer has any people, we're done.
094:         while (side1.size() != 0) {
095: 
096:             // Send the fastest person back from side2 to side1
097:             eTime += sendOver(1, true, side2, side1);
098: 
099:             /*
100:             Send the two slowest people from side1 to side2.
101:             There must be at least two people, since we weren't done,
102:             and above we've just sent one more back.
103:              */
104:             eTime += sendOver(2, false, side1, side2);
105: 
106:             // Check again to see if we're done.
107:             if (side1.size() == 0) {
108:                 return eTime;
109:             }
110: 
111:             // Send the fastest person back from side2 to side1
112:             eTime += sendOver(1, true, side2, side1);
113: 
114:             // Send the two fastest from side1 to side2.
115:             eTime += sendOver(2, true, side1, side2);
116:         }
117: 
118:         return eTime;
119:     }
https://tsenkov.net/2013/04/08/topcoder-srm-146-div2-problems-and-solutions
Bridge Crossing wasn't very hard to see through (luck maybe). The algorithm is consistent of the repetition of this complex action:
  1. Get the fastest couple on the left side;
  2. Return the fastest element back on the right side;
  3. Get the slowest (with highest sum, also) couple on the left side;
  4. Return the second element passed in step 1. back on the right.
​​This is repeated until all elements are on the left side.
For ease I am sorting the elements at the beginning and then always insert at sorted positions the elements I am moving.

    
public int minTime(int[] times)
    {
        Array.Sort(times);
        if (times.Length == 1)
        {
            return times[0];
        }
        else if (times.Length == 2)
        {
            return Math.Max(times[0], times[1]);
        }
 
        List<int> right = new List<int>(times);
        List<int> left = new List<int>();
 
        int time = 0;
        bool moveLeft = true;
        // -1 0 1
        int probeStage = 1;
        while (right.Count > 0)
        {
            if (moveLeft)
            {
                int first, second;
                switch (probeStage)
                {
                    case 1:
                        first = right[0];
                        second = right[1];
                        left.Insert(0, first);
                        left.Insert(1, second);
                        right.RemoveRange(0, 2);
                        time += second;
                        probeStage = -1;
                        break;
                    case 0:
                        int lastIndex = right.Count - 1;
                        first = right[lastIndex - 1];
                        second = right[lastIndex];
                        left.Add(first);
                        left.Add(second);
                        right.RemoveRange(lastIndex - 1, 2);
                        time += second;
                        break;
                }
                moveLeft = false;
            }
            else
            {
                int firstLeft = left[0];
                int firstRight = right[0];
                left.RemoveAt(0);
                int index = 1;
                if (firstLeft < firstRight)
                {
                    index = 0;
                }
                right.Insert(index, firstLeft);
                probeStage++;
                moveLeft = true;
                time += firstLeft;
            }
        }
        return time;
    }


Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts