考虑有一条水平河流穿过其中心的二维地图。南岸有 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 问题的变体。以下是解决问题的步骤。
- 根据南 x 坐标的递增顺序对南北对进行排序。
- 如果两个南 x 坐标相同,则按北 x 坐标的升序排序。
- 现在找到北 x 坐标的最长递增子序列。
- 需要注意的一件事是,在递增的子序列中,一个值可以更大也可以等于其先前的值。
我们还可以根据北 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) 中完成。
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
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 现场工作专业课程和学生竞争性编程现场课程。