Skip to content
Related Articles

Related Articles

Save Article
Improve Article
Save Article
Like Article

Dynamic Programming | Building Bridges

  • Difficulty Level : Medium
  • Last Updated : 19 Jul, 2021

Consider a 2-D map with a horizontal river passing through its center. There are n cities on the southern bank with x-coordinates a(1) … a(n) and n cities on the northern bank with x-coordinates b(1) … b(n). You want to connect as many north-south pairs of cities as possible with bridges such that no two bridges cross. When connecting cities, you can only connect city a(i) on the northern bank to city b(i) on the southern bank. Maximum number of bridges that can be built to connect north-south pairs with the aforementioned constraints.
 

null

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

The values in the upper bank can be considered as the northern x-coordinates of the cities and the values in the bottom bank can be considered as the corresponding southern x-coordinates of the cities to which the northern x-coordinate city can be connected.
Examples: 
 



Input : 6 4 2 1
        2 3 6 5
Output : Maximum number of bridges = 2
Explanation: Let the north-south x-coordinates
be written in increasing order.

1  2  3  4  5  6
  \  \
   \  \        For the north-south pairs
    \  \       (2, 6) and (1, 5)
     \  \      the bridges can be built.
      \  \     We can consider other pairs also,
       \  \    but then only one bridge can be built 
        \  \   because more than one bridge built will
         \  \  then cross each other.
          \  \
1  2  3  4  5  6 

Input : 8 1 4 3 5 2 6 7 
        1 2 3 4 5 6 7 8
Output : Maximum number of bridges = 5

 

Approach: It is a variation of LIS problem. The following are the steps to solve the problem.
 

  1. Sort the north-south pairs on the basis of increasing order of south x-coordinates.
  2. If two south x-coordinates are same, then sort on the basis of increasing order of north x-coordinates.
  3. Now find the Longest Increasing Subsequence of the north x-coordinates.
  4. One thing to note that in the increasing subsequence a value can be greater as well as can be equal to its previous value.

We can also sort on the basis of north x-coordinates and find the LIS on the south x-coordinates.
 

CPP




// C++ implementation of building bridges
#include <bits/stdc++.h>
 
using namespace std;
 
// north-south coordinates
// of each City Pair
struct CityPairs
{
    int north, south;
};
 
// comparison function to sort
// the given set of CityPairs
bool compare(struct CityPairs a, struct CityPairs b)
{
    if (a.south == b.south)
        return a.north < b.north;
    return a.south < b.south;
}
 
// function to find the maximum number
// of bridges that can be built
int maxBridges(struct CityPairs values[], int n)
{
    int lis[n];
    for (int i=0; i<n; i++)
        lis[i] = 1;
         
    sort(values, values+n, compare);
     
    // logic of longest increasing subsequence
    // applied on the northern coordinates
    for (int i=1; i<n; i++)
        for (int j=0; j<i; j++)
            if (values[i].north >= values[j].north
                && lis[i] < 1 + lis[j])
                lis[i] = 1 + lis[j];
         
         
    int max = lis[0];
    for (int i=1; i<n; i++)
        if (max < lis[i])
            max = lis[i];
     
    // required number of bridges
    // that can be built       
    return max;       
}
 
// Driver program to test above
int main()
{
    struct CityPairs values[] = {{6, 2}, {4, 3}, {2, 6}, {1, 5}};
    int n = 4;
    cout << "Maximum number of bridges = "
             << maxBridges(values, n);   
    return 0;
}

Java




// Java Program for maximizing the no. of bridges
// such that none of them cross each other
 
import java.util.*;
 
class CityPairs // Create user-defined class
{
    int north, south;
    CityPairs(int north, int south) // Constructor
    {
        this.north = north;
        this.south = south;
    }
}
// Use Comparator for manual sorting
class MyCmp implements Comparator<CityPairs>
{
    public int compare(CityPairs cp1, CityPairs cp2)
    {
        // If 2 cities have same north coordinates
        // then sort them in increasing order
        // according to south coordinates.
        if (cp1.north == cp2.north)
            return cp1.south - cp2.south;
 
        // Sort in increasing order of
        // north coordinates.
        return cp1.north - cp2.north;
    }
}
public class BuildingBridges {
    // function to find the max. number of bridges
    // that can be built
    public static int maxBridges(CityPairs[] pairs, int n)
    {
        int[] LIS = new int[n];
        // By default single city has LIS = 1.
        Arrays.fill(LIS, 1);
 
        Arrays.sort(pairs, new MyCmp()); // Sorting->
                                         // calling
        // our self made comparator
 
        // Logic for Longest increasing subsequence
        // applied on south coordinates.
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (pairs[i].south >= pairs[j].south)
                    LIS[i] = Math.max(LIS[i], LIS[j] + 1);
            }
        }
        int max = LIS[0];
        for (int i = 1; i < n; i++) {
            max = Math.max(max, LIS[i]);
        }
 
        // Return the max number of bridges that can be
        // built.
        return max;
    }
 
    // Driver Program to test above
    public static void main(String[] args)
    {
        int n = 4;
        CityPairs[] pairs = new CityPairs[n];
        pairs[0] = new CityPairs(6, 2);
        pairs[1] = new CityPairs(4, 3);
        pairs[2] = new CityPairs(2, 6);
        pairs[3] = new CityPairs(1, 5);
        System.out.println("Maximum number of bridges = "
                           + maxBridges(pairs, n));
    }
}

Output: 
 

Maximum number of bridges = 2

Time Complexity: O(n2)

Approach – 2 (Optimization in LIS )

Note – This is the variation/Application of Longest Increasing Subsequence (LIS).

Step -1 Initially let the one side be north of the bridge and other side be south of the bridge.



Step -2 Let we take north side and sort the element with respect to their position.

Step -3 As per north side is sorted therefore it is increasing and if we apply LIS on south side then we will able to get the non-overlapping bridges.

Note – Longest Increasing subsequence can be done in O(NlogN) using Patience sort.

The main optimization lies in the fact that smallest element have higher chance of contributing in LIS.

Input: 6 4 2 1

          2 3 6 5

Step 1 –Sort the input at north position of bridge.

1 2 4 6  

5 6 3 2

Step -2 Apply LIS on South bank that is 5 6 3 2

In optimization of LIS if we find an element which is smaller than current element then we Replace the halt the current flow and start with the new smaller element. If we find larger element than current element we increment the answer.  

5————- >6 (Answer =2) HALT we find 3 which is smaller than 6  

3 (Answer = 1) HALT we find 2 which is smaller than 3

2 (Answer=1)

FINAL ANSWER = 2

C++




#include<bits/stdc++.h>
using namespace std;
 
int non_overlapping_bridges(vector<pair<int,int>> &temp,int n)
{
    //Step - 1 Sort the north side.
    sort(temp.begin(),temp.end());
    // Create the Dp array to store the flow of non overlapping bridges.
    // ans-->Store the final max number of non-overlapping bridges.
    vector<int> dp(n+1,INT_MAX);
    int ans=0;
    for(int i=0;i<n;i++)
    {
        int idx=lower_bound(dp.begin(),dp.end(),temp[i].second)-dp.begin();
        dp[idx]=temp[i].second;
        ans=max(ans,idx+1);
    }
    return ans;
}
 
int main()
{
    int n=4;
    vector<pair<int,int>> temp;
    temp.push_back(make_pair(6,2));
    temp.push_back(make_pair(4,3));
    temp.push_back(make_pair(2,6));
    temp.push_back(make_pair(1,5));
     
    cout<<non_overlapping_bridges(temp,n)<<endl;
    return 0;
}

OUTPUT – 2

Time Complexity – O(NlogN)

Space Complexity – O(N)

Problem References: 
https://www.geeksforgeeks.org/dynamic-programming-set-14-variations-of-lis/
Solution References: 
https://www.youtube.com/watch?v=w6tSmS86C4w
This article is contributed by Ayush Jauhari. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
 




My Personal Notes arrow_drop_up
Recommended Articles
Page :