• 航线——线性dp


    题目描述

    Palmia 河在某国从东向西流过,并把该国分为南北两个部分。河的两岸各有 n 个城市,且北岸的每一个城市都与南岸的某个城市是友好城市,而且对应的关系是一一对应的。现在要求在两个友好城市之间建立一条航线,但由于天气的关系,所有航线都不能相交,因此,就不可能给所有的友好城市建立航线。

    问题:当城市个数和友好关系建立之后,选择一种修建航线的方案,能建最多的航线而不相交。(若有多种方案,修建航线最多且城市数量相同,选择从前到后城市标号字典序小的那种方案.)

    输入格式

    输入由若干行组成,第一行有一个整数,n(1≤n≤10000);表示城市数。第2n+1行依次是南岸城市的北岸友好城市编号。

    输出格式

    输出共两行,第一行是建立航线的数量。第二行是建立航线的北岸城市编号。

    样例

    样例输入

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

    样例输出

    8
    7 9 16 18 19 21 22 63

    怎么看着这么像友好城市呢...(如果不输出路径的话
    可为什么放在区间dp里???迷惑
    反正我按友好城市 不下降子序列 做的。
    路径的话保存转到 i 的编号即可。最后递归输出。
    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int MAXN = 1e4+3;
    
    int a[MAXN], n, pa[MAXN], ans, tot,la, f[MAXN];
    
    void Print(int x){
        if(pa[x]!=-1){
            Print(pa[x]); printf("%d ",a[x]);
        }else{
            printf("%d ",a[x]);
        }
    }
    int main(){
        scanf("%d",&n); memset(pa,-1,sizeof(pa));
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        if(n==1){
            printf("1
    %d",a[1]); return 0;
        }
        for(int i=1;i<=n;i++){
            f[i]=1; 
            for(int j=1;j<i;j++){
                if(a[i]>=a[j] && f[i]<f[j]+1) {f[i]=f[j]+1;pa[i]=j;}
                if(ans<f[i]) ans=f[i],la=i;
            }
        }
        printf("%d
    ",ans);
        Print(la);
        return 0;
    }
    
    

    完了?

    完...
    蛋。

    总有一个点过不去...
    如果输入全倒序呢?
    显然在下面这个循环中,如果 a[i+1]<a[i]的话,里面的if语句是不会执行的。那最后 la 也就是最初的 0,是没有办法输出路径的。
    for(int i=1;i<=n;i++){
            f[i]=1; 
            for(int j=1;j<i;j++){
                if(a[i]>=a[j] && f[i]<f[j]+1) {f[i]=f[j]+1;pa[i]=j;}
                if(ans<f[i]) ans=f[i],la=i;
            }
        }
    
    

    于是需要初始化 la。当对任一 i 都有 a[i+1]<a[i] 的时候,我们只能建立一条航线。那这条航线肯定就是从 1 号城市到 对岸的最后一个城市。这时,我们就可以得到 100 了。

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int MAXN = 1e4+3;
    
    int a[MAXN], n, pa[MAXN], ans, tot,la, f[MAXN];
    
    void Print(int x){
        if(pa[x]!=-1){//如果x有父亲
            Print(pa[x]); printf("%d ",a[x]);//先输出父亲,再输出x
        }else{//x没父亲(x是第一个)
            printf("%d ",a[x]);//直接输出
        }
    }
    int main(){
        ans=1; la=1; //CaO...beyond expression...mamaipi...需要考虑特殊情况
        scanf("%d",&n); memset(pa,-1,sizeof(pa));
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=n;i++){
            f[i]=1;
            for(int j=1;j<i;j++){
                if(a[i]>=a[j] && f[i]<f[j]+1){//不下降
                    f[i]=f[j]+1;
                    pa[i]=j;//记录是由谁到i的
                }
                if(ans<f[i]) ans=f[i],la=i;//记录最后一个,以便递归输出
            }
        }
        printf("%d
    ",ans);
        Print(la);//由la递归输出
        return 0;
    }
     
  • 相关阅读:
    Sql Server Tempdb原理-日志机制解析实践
    Sql Server 高频,高并发访问中的键查找死锁解析
    SQL Server 高并发Insert数据解析,实践
    Sql Server 2012新特性 Online添加非空栏位.
    SQL Server 利用批量(batchsize)提交加快数据生成/导入
    SQL Server 最小化日志操作解析,应用
    SQL Server 统计信息(Statistics)-概念,原理,应用,维护
    SQL Server 索引知识-应用,维护
    BigDecimal加减乘除计算
    如何判断一个String字符串不为空或这不为空字符串
  • 原文地址:https://www.cnblogs.com/Siegfried-L/p/12864085.html
Copyright © 2020-2023  润新知