• 动态规划-最长不下降子序列


    代码:

    #include <stdio.h>
    #include <memory.h>
    #include <math.h>
    #include <string>
    #include <vector>
    #include <set>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <map>
    
    
    #define I scanf
    #define OL puts
    #define O printf
    #define F(a,b,c) for(a=b;a<c;a++)
    #define FF(a,b) for(a=0;a<b;a++)
    #define FG(a,b) for(a=b-1;a>=0;a--)
    #define LEN 101
    #define MAX 1<<30
    #define V vector<int>
    
    using namespace std;
    
    int a[LEN];
    int dp[LEN];
    int n;
    
    void printAns(int cnt,int pos,V vec){
        vec.insert(vec.begin(),a[pos]);
        int obj=dp[pos--]-1;
        while(pos>0){
            if(dp[pos]==obj)
                printAns(cnt-1,pos,vec);
            pos--;
        }
        if(cnt==1){
            int i;
            FF(i,vec.size())
                O("%d ",vec[i]);
            OL("");
        }
    }
    
    void DP_n2(){
        int i,j,p;
        int ans=0;
        F(i,1,n+1){
            dp[i]=1;
            F(j,1,i){
                if(a[j]<a[i])
                    dp[i]=max(dp[i],dp[j]+1);
            } 
            if(dp[i]>ans){
                ans=dp[i];
                p=i;
            }
        }
        O("ans=%d p=%d
    序列 :
    ",ans,p);
        F(i,1,n+1)O("%d ",a[i]) ;
        OL("
    DP数组 :");
        F(i,1,n+1)O("%d ",dp[i]) ;
        OL("");
        V vec;
        OL("所有LIS :");
        printAns(ans,p,vec);
    } 
    
    void DP_nLogn(){
        int i,j,top=0;
        F(i,1,n+1){
            if(top==0 || dp[top-1]<a[i]) 
                dp[top++]=a[i];
            else{
                int pos=lower_bound(dp,dp+top,a[i])-dp;
                dp[pos]=a[i];
            }
        }
        printf("%d
    ",top);
        OL("DP数组: ");
        F(i,0,top)O("%d ",dp[i]);
        OL("
    ") ;
    }
    int main()
    {   
    //dilworth定理:LIS 长度   等于  LIS 子序列 个数
        freopen("LIS.txt","r",stdin);
        int i,j;
        I("%d",&n);
        F(i,1,n+1){
            I("%d",&a[i]);
        }
        
        DP_nLogn();
        DP_n2();
        return 0;
    }
    View Code

    测试数据:

    11
    1 3 7 6 8 5 3 2 7 2 9
    

    OJ:导弹拦截

    #include <stdio.h>
    #include <memory.h>
    #include <math.h>
    #include <string>
    #include <vector>
    #include <set>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <map>
    
    
    #define I scanf
    #define OL puts
    #define O printf
    #define F(a,b,c) for(a=b;a<c;a++)
    #define FF(a,b) for(a=0;a<b;a++)
    #define FG(a,b) for(a=b-1;a>=0;a--)
    #define LEN 100001
    #define MAX 1<<30
    #define V vector<int>
    
    using namespace std;
    
    int a[LEN];
    int dp1[LEN];//increase
    int dp2[LEN];//decrease
    
    bool cmp(int x,int y){
        return x>y;
    }
    
    int main(){
        freopen("D:/CbWorkspace/动态规划/导弹拦截.txt","r",stdin);
        int i,n=0; 
        while(I("%d",&a[++n])>0);
        n--;
        fill(dp2,dp2+n+1,MAX);
        int len1=0,len2=0;
        F(i,1,n+1){
            //记录递增dp
            int p1=upper_bound(dp1+1,dp1+1+n,a[i],cmp)-dp1;    //在递减序列中进行操作 
            //记录递减dp(初始化Inf)
            int p2=lower_bound(dp2+1,dp2+1+n,a[i])-dp2;        //在递增序列中进行操作 
            dp1[p1]=a[i] ;
            dp2[p2]=a[i] ;
            len1=max(len1,p1);
            len2=max(len2,p2);
            int s=0;
        }
        O("%d
    %d",len1,len2);
        return 0;
    }
    View Code

    OJ : 合唱队形

    #include <stdio.h>
    #include <memory.h>
    #include <math.h>
    #include <string>
    #include <vector>
    #include <set>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <map>
    
    
    #define I scanf
    #define OL puts
    #define O printf
    #define F(a,b,c) for(a=b;a<c;a++)
    #define FF(a,b) for(a=0;a<b;a++)
    #define FG(a,b) for(a=b-1;a>=0;a--)
    #define LEN 100001
    #define MAX 1<<30
    #define V vector<int>
    
    using namespace std;
    
    int dp1[LEN] ;
    int dp2[LEN] ;
    int a[LEN] ;
    int max1[LEN] ;
    int max2[LEN] ;
    
    bool cmp(int x,int y){
        return x>y;
    }
    
    int main(){
    //    freopen("D:/CbWorkspace/动态规划/合唱队形.txt","r",stdin);
        int n,i,j;
        I("%d",&n);
        FF(i,n)
            I("%d",&a[i]);
        int max_ans=0;
        FF(i,n){
            dp1[i]=1;
            FF(j,n){
                if(a[j]<a[i]){
                    dp1[i]=max(dp1[i],dp1[j]+1);
                }
            }
            max_ans=max(max_ans,dp1[i]);
            max1[i]=max_ans;
        }
        max_ans=0;
        for(i=n-1;i>=0;i--){
            dp2[i]=1;
            for(j=n-1;j>i;j--){
                if(a[i]>a[j]){
                    dp2[i]=max(dp2[i],dp2[j]+1);
                }
            }
            max_ans=max(max_ans,dp2[i]);
            max2[i]=max_ans;
        }
        int ans=0;
        FF(i,n-1){
            int t=max1[i]+max2[i+1];
            ans=max(ans,t);
        }
        O("%d",n-ans);
        return 0;
    }
    View Code
  • 相关阅读:
    训练20191009 2018-2019 ACM-ICPC, Asia East Continent Finals
    [学习笔记] 有上下界网络流
    [HDU4609] 3-idiots
    [HDU1402] A * B Problem Plus
    [HNOI2017] 礼物
    训练20191007 2017-2018 ACM-ICPC Latin American Regional Programming Contest
    [ZJOI2014] 力
    训练20191005 2017-2018 ACM-ICPC Asia East Continent League Final
    [一本通学习笔记] 树链剖分
    [一本通学习笔记] 快速幂
  • 原文地址:https://www.cnblogs.com/TQCAI/p/8428598.html
Copyright © 2020-2023  润新知