首页 > 其他分享 >线性dp

线性dp

时间:2024-02-17 17:44:37浏览次数:31  
标签:22 int MAX 样例 序列 ans 线性 dp

线性动态规划:


  • 不用多说,主要应用于求上升子序列,下降子序列等
  • 直接看例题:

样例输入:

13 7 9 16 38 24 37 18 44 19 21 22 63 15

样例输出:

max=8
7 9 16 18 19 21 22 63

解:

#include<bits/stdc++.h>
using namespace std;

const int MAX = 1050;

int n, ans;
int f[MAX], a[MAX], pre[MAX], en;
//f[i]表示前i个数中的最大上升序列
//pre[]用来打印路径

void putout(int x){
    if(x == 0) return ;
    putout(pre[x]);//递归一直求该序列中的上一个数
    printf("%d ",a[x]);
}

int main(){
    
    int x;
    while(~scanf("%d",&x)) a[++n] = x;

    for(int i=1; i<=n; i++){
        f[i] = 1;
        for(int j=1; j<i; j++){  //从1到i中比i小的个数
            if(a[i]>a[j] and f[i]<f[j]+1){
                f[i] = f[j] + 1;
                pre[i] = j;  //标记,i的前一个数为j;
            }
        }
        if(ans < f[i]){
            ans = f[i];
            en = i;
        }
    }
    printf("max=%d\n",ans);
    putout(en); //递归输出
   
    return 0;   
}


经过第一道例题,我们已经了解线性dp的特点以及大致模板了。现在上难度:

样例输入:

7
22 4
2 6
10 3
15 12
9 8
17 17
4 2

样例输出:

4

解:

将南岸城市和北岸城市在坐标图中表示出来,将一一对应的两城市连线,容易发现,若连线交叉,则会发生事故。那么我们可以知道按南岸城市坐标从小到大排序,相对应的北岸城市坐标求最大上升序列个数即为答案。

代码实现如下:
#include<bits/stdc++.h>
using namespace std;

const int MAX = 5050;

int n, m, tot;
int ans;
int f[MAX], ntos[10050];

int main(){

    int x, y, Nmax = 0;

    scanf("%d",&n);
    for(int i=1; i<=n; i++){
        scanf("%d%d",&x, &y);
        ntos[x] = y;  //表示南岸坐标为x的城市对应的北岸坐标
        Nmax = max(Nmax, x); //求出南岸最大坐标
    }

    //按南岸城市坐标大小依次遍历
    for(int i=1; i<=Nmax; i++){
        if(ntos[i])
        {
            int a = ntos[i];
            ntos[i] = 0;
            ntos[++tot] = a;
        }
    }
    //即可转化为求最大上升序列

    for(int i=1; i<=n; i++){
        f[i] = 1;
        for(int j=1; j<i; j++){
            if(ntos[i] > ntos[j]){
                f[i] = max(f[i], f[j]+1);
            }
        }
        ans=max(ans, f[i]);
    }

    printf("%d", ans);

    return 0;
}

标签:22,int,MAX,样例,序列,ans,线性,dp
From: https://www.cnblogs.com/zyzAqr/p/18018162

相关文章

  • DP总结
    DP总结1.背包DP-0/1背包-完全背包-多重背包-分组背包-依赖背包-二维背包-树形背包DP0/1背包朴素版点击查看代码#include<bits/stdc++.h>usingnamespacestd;constintmaxn=1010;//f[i][j]表示前i个物品,体积不超过j时的最大价值//不选第i个物品时,f[i][j]......
  • 回顾复习之线性DP
    概念具有线性阶段划分的动态规划算法叫作线性动态规划(简称线性DP)。若状态包含多个维度,则每个维度都是线性划分的阶段,也属于线性DP,如下图所示:如果状态包含多个维度,但是每个维度上都是线性划分的阶段,也属于线性DP。比如背包问题、区间DP、数位DP等都属于线性DP。例题求最......
  • 动态规划--一维dp和二维dp
    在解决背包问题时,使用一维动态规划数组和二维动态规划数组都是常见的方法,选择哪种方式取决于问题的特点和解法的需要。使用一维DP数组的情况:状态转移方程只涉及到上一行的元素:当状态转移方程只涉及到上一行的元素时,可以使用一维DP数组。这样能够降低空间复杂度,使算法更为简......
  • DP总结
    DP(动态规划)简介动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。由于动态规划并不是某种具体的算法,而是一种解决特定问题的方法,因此它会出现在各式各样的数据结构中,与之相关的题目种类也更为繁杂。DP基础1.必要前提需要满足三个条件:最优子......
  • 树形dp
    树形dp模型:给定一颗有n个节点的树,任选一个节点为根节点,从而定义出每个节点的深度和每棵子树的根。基本思路:1.建树2.列出动态转移方程典型例题:没有上司的舞会#include<bits/stdc++.h>usingnamespacestd;intn,l,k,ans;vector<int>son[6600];intf[6600][2],v[6600],r......
  • 区间DP
    先看一下模板点击查看代码//f[i][j]表示从i到j区间的值for(intlen=2;len<=n;len++)//len表示区间长度{ for(inti=1;i+len-1<=n;i++)//关系一般为2<=i<=k<j<=n { intj=i+len-1;//j的求值,开始点+区间长度-1 for(intk=i;k<j;k++) { f[i][j]=min/max(状态转移......
  • 坐标DP
    坐标DP相较来说会比较简单。直接上例题1.坐标遍历问题传纸条点击查看代码#include<bits/stdc++.h>usingnamespacestd;constintN=120;intm,n;intg[N][N],f[N][N][N];intans;intmain(){ cin>>n>>m; for(inti=1;i<=n;i++) { for(intj=1;j<=m;j++) { ......
  • 关于动态规划(Dynamic Programming)的若干思考 ------ [2.线性dp]
    线性dp的两个经典题目:最长上升子序列(LIS)and最长公共子序列(LCS)1.LIS核心代码#include<bits/stdc++.h>usingnamespacestd;constintmaxn=2024;intcnt=0,ans=1;intf[maxn],a[maxn],c[maxn];voidout(intx){ if(x==0)return; out(c[x]); cout<<a[x]<<......
  • 线性dp
    基本应用:最长上升子序列:题目描述设有由n个不相同的整数组成的数列,记为:b(1)、b(2)、……、b(n)且b(i)<>b(j)(i<>j),若存在i1<i2<i3<…<ie且有b(i1)<b(i2)<…<b(ie)则称为长度为e的不下降序列。程序要求,当原数列出之后,求出最长的上升序列。例如13,7,9,16,38,24,37,18,44,19,21,22,63......
  • dp总结(背包,线性,区间,坐标,树形)
    背包dp0/1背包这种背包会提供可选的物品,背包的容积以及每件物品的价值,并且在选择物品是每件物品只有选一件或不选两种状态。例题输入4512243445输出8二维解法代码//状态转移方程为:f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i])#include"bits/stdc++.h"using......