题目传送门

一、题目分析

条件一:每个城市只能建立一座桥

条件二:所有的桥与桥之间不能相交

目标:最多能建立多少座桥

步骤

  1. 通过排序,固定自变量的顺序

  2. 找因变量的最大上升子序列。(原因:找出的上升子序列越长,与下面自变量的匹配数量就越大,也就是修的桥数越多。)

AcWing 1012. 友好城市

总结:

  • 本题还是有一些思维的难度,需要对问题进行转化。用数对描述问题比较好想,为什么要按左端点进行排序呢?似乎对于数对而言,大多数情况需要固定一个端点,比如区间合并,如果我们能想到这是一个用数对描述的问题,不妨先想一下是不是在按左端点排序一下。

  • 按左端点排序后,一般的思路就是对比右端点(要不按左端点排序就没啥意义了~)。此时就是把二维的概念转化为一维的概念。本题是根据右端点的逆序关系来说明当前路线与前序的矛盾关系,我们把图画出来,现在聚焦到一维上面(就是是图的上侧),发现,如果是严格单调上升的序列,越长的话,修建的桥数越多。

  • \(lis\)的原问题出发,思考以上方的每一个数字结尾,会产生多少座桥,也就是问题的答案。

  • 思考一个复杂问题,从有一定的套路,将问题进行转化,然后再从最朴素的模板问题出发,思考问题的本质。

二、实现代码

#include <bits/stdc++.h>

using namespace std;
//线段,二维,一般用PII,因为可以不需要写cmp,直接按first排序
typedef pair<int, int> PII;

const int N = 5010;
PII a[N];   //南岸和北岸的一对友好城市的坐标
int f[N];   //记录以f[i]为结尾的一对友好城市时的,不产生交叉的最多城市对数
int n;      //n组友好城市

int main() {
    cin >> n;
    //读入友好城市对
    for (int i = 1; i <= n; i++)cin >> a[i].first >> a[i].second;
    //按first排序,则南岸城市坐标由小到大
    sort(a + 1, a + 1 + n);

    int mx = 0;
    //LIS 正向
    for (int i = 1; i <= n; i++) {
        f[i] = 1;
        for (int j = 1; j < i; j++)
            //如果南岸城市坐标由小到大,那么北岸也必须由小到大,否则就是交叉
            if (a[i].second > a[j].second)
                f[i] = max(f[i], f[j] + 1);
        mx = max(mx, f[i]);
    }
    printf("%d\n", mx);
    return 0;
}

相关文章:

  • 2021-06-21
  • 2022-12-23
  • 2022-01-23
  • 2021-06-03
  • 2021-10-11
  • 2021-06-15
  • 2022-12-23
  • 2021-05-23
猜你喜欢
  • 2022-01-15
  • 2021-09-27
  • 2022-12-23
  • 2021-08-27
  • 2021-06-22
  • 2021-11-26
相关资源
相似解决方案