동적 프로그래밍-(떨어지지 않고 가장 긴 하위 시퀀스)

참조 : https://oi-wiki.org/dp/basic/

O (n ^ 2) 알고리즘

매번 처음부터 스캔하여 최상의 답변을 찾으십시오.

int a[MAXN], d[MAXN];
int dp() {
    
    
  d[1] = 1;
  int ans = 1;
  for (int i = 2; i <= n; i++) {
    
    
    for (int j = 1; j < i; j++)
      if (a[j] <= a[i]) {
    
    
        d[i] = max(d[i], d[j] + 1);
        ans = max(ans, d[i]);
      }
  }
  return ans;
}

O (nlogn) 알고리즘 이분법

이 기사 https://www.cnblogs.com/itlqs/p/5743114.html
여기에 사진 설명 삽입
참조 하면 코드는 다음과 같습니다.

for (int i = 0; i < n; ++i) scanf("%d", a + i);
memset(dp, 0x1f, sizeof dp);
mx = dp[0];
for (int i = 0; i < n; ++i) {
    
    
  *std::upper_bound(dp, dp + n, a[i]) = a[i];
}
ans = 0;
while (dp[ans] != mx) ++ans;

샘플 질문 : https://vijos.org/p/1303

기술

특정 국가에서는 적의 미사일 공격을 방어하기 위해 미사일 차단 시스템을 개발했습니다. 그러나이 미사일 요격 시스템에는 결함이 있습니다. 첫 번째 포탄이 어떤 높이에도 도달 할 수 있지만 이후의 각 포탄은 이전 포탄보다 높을 수 없습니다. 어느 날 레이더가 적의 미사일 공격을 포착했습니다. 시스템이 아직 실험 단계에 있기 때문에 시스템이 하나뿐이므로 모든 미사일을 요격하지 못할 수도 있습니다.

체재

입력 형식

입력 데이터는 한 줄뿐입니다.이 줄에는 반폭 쉼표로 구분 된 여러 데이터가 포함되어 있으며 미사일의 높이를 차례로 나타냅니다 (최대 20 개의 미사일이 있고 높이는 30,000 이하의 양의 정수입니다. ).

출력 형식

한 줄의 출력 데이터 만 있고이 줄에는 쉼표로 구분 된 두 개의 데이터가 있습니다. 첫 번째 데이터는이 시스템이 요격 할 수있는 최대 미사일 수를 나타내고 두 번째 데이터는 모든 미사일을 요격하기 위해 이러한 시스템을 얼마나 더 추가해야하는지 나타냅니다.

예 1

샘플 입력 1

389,207,155,300,299,170,158,65

샘플 출력 1

6,1

한도

각 테스트 포인트의 시간 제한은 1 초입니다.

문제 해결

암호

#include <algorithm>
#include <iostream>
#include <stack>
#include <string>
#include <vector>
using namespace std;
const int maxn = 1e5 + 2;
int dp[maxn];  // dp[k]表示长度为k的不下降子序列末尾元素的最小值
// int minh[maxn];  //记录从第i项开始,剩下最大能消灭的导弹数量
vector<int> v;

int up_bound(int l, int r, int x) {
    
      //找到第一个大于x的数的下标
    while (l < r) {
    
    
        int mid = (r + l) / 2;
        if (x >= dp[mid])
            l = mid + 1;
        else
            r = mid;
    }
    return l;
}
int down_bound(int l, int r, int x) {
    
      //找到第一个小于等于x的数的下标
    for (int i = l; i <= r; i++)
        if (dp[i] <= x) return i;
    return r;
}

int main() {
    
    
    char ch;
    int n;
    while (true) {
    
    
        scanf("%d", &n);
        v.push_back(n);
        ch = getchar();
        if (ch == '\n') break;
    }

    v.push_back(0);
    reverse(v.begin(), v.end());

    int len = 1;
    dp[1] = v[1];
    for (int i = 2; i < v.size(); i++) {
    
      //求出最长不降子序列
        if (v[i] >= dp[len]) {
    
    
            dp[++len] = v[i];
        } else {
    
    
            int up = up_bound(1, len, v[i]);
            dp[up] = v[i];
        }
    }

    cout << len << ",";
    //第二问就出最大下降子序列
    len = 1;
    dp[1] = v[1];
    for (int i = 2; i < v.size(); i++) {
    
    
        if (v[i] < dp[len])
            dp[++len] = v[i];
        else {
    
    
            int down = down_bound(1, len, v[i]);
            dp[down] = v[i];
        }
    }

    cout << len - 1 << endl;

    return 0;
}
/*90 103 99 83 102 70 86 70 99 71*/

추천

출처blog.csdn.net/qq_45349225/article/details/109405029