📜  动态规划 |搭建桥梁

📅  最后修改于: 2021-09-17 07:43:25             🧑  作者: Mango

考虑有一条水平河流穿过其中心的二维地图。南岸有 n 个城市,x 坐标为 a(1) … a(n),北岸有 n 个城市,x 坐标为 b(1) … b(n)。您希望使用桥梁连接尽可能多的南北城市对,以免两座桥梁交叉。连接城市时,只能连接北岸的城市a(i)和南岸的城市b(i)。可以建造的最大数量的桥梁来连接具有上述约束的南北对。

无效的

上岸的值可以认为是城市的北 x 坐标,下岸的值可以认为是北 x 坐标城市可以连接到的城市对应的南 x 坐标。
例子:

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

方法:这是 LIS 问题的变体。以下是解决问题的步骤。

  1. 根据南 x 坐标的递增顺序对南北对进行排序。
  2. 如果两个南 x 坐标相同,则按北 x 坐标的升序排序。
  3. 现在找到北 x 坐标的最长递增子序列。
  4. 需要注意的一件事是,在递增的子序列中,一个值可以更大也可以等于其先前的值。

我们还可以根据北 x 坐标进行排序,并在南 x 坐标上找到 LIS。

CPP
// C++ implementation of building bridges
#include 
 
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= values[j].north
                && lis[i] < 1 + lis[j])
                lis[i] = 1 + lis[j];
         
         
    int max = lis[0];
    for (int i=1; iJava
// 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
{
    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));
    }
}


C++
#include
using namespace std;
 
int non_overlapping_bridges(vector> &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 dp(n+1,INT_MAX);
    int ans=0;
    for(int i=0;i> 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<


输出:

Maximum number of bridges = 2

时间复杂度:O(n 2 )

方法 – 2(LIS 中的优化)

注 –这是最长递增子序列 (LIS) 的变体/应用。

步骤-1 最初让一侧在桥的北边,另一侧在桥的南边。

步骤 -2 让我们取北侧并根据它们的位置对元素进行排序。

步骤-3 根据北侧排序,因此它正在增加,如果我们在南侧应用 LIS,那么我们将能够获得不重叠的桥梁。

注意——最长递增子序列可以使用耐心排序在 O(NlogN) 中完成。

C++

#include
using namespace std;
 
int non_overlapping_bridges(vector> &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 dp(n+1,INT_MAX);
    int ans=0;
    for(int i=0;i> 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<

输出 – 2

时间复杂度 – O(NlogN)

空间复杂度 – O(N)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程