zoukankan      html  css  js  c++  java
  • 连线

    传送门

    题目描述
    上下有两个长度为n、位置对应的序列A、B, 其中数的范围均为1~n。若abs(A[i]-B[j]) <= 4, 则A[i]与B[j]间可以连一条边。现要求在边与边不相交的情况下的最大的连边数量。 n <= 10^5
    输入格式
    第一行给出数字N 接下来N个数字,代表第一个数列 再接下来N个数字,代表第二个数列
    输出格式
    在边与边不相交的情况下的最大的连边数量

    题意

    现在有两行数字,保证全排列
    两行任意两个数的差<=4即可连线
    求每条线不相交的情况下,最多可连多少条线

    解答

    暴力DP

    最开始想的是DFS暴力枚举然后又想到去推DP
    dp[i][j]表示第一行选到第i个,第二行选到第j个的最大连线数

    dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
    要么选,要么不选

    可以选就:
    if(abs(a[i]-a[j])<=4)dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);

    for(int i=1;i<=n;i++){
          for(int j=1;j<=n;j++){
                f[i][j]=max(dp[i-1][j],dp[i][j-1]);
                if (abs(a[i]-b[j])<=4)dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
          }
    }
    

    但由于10^5for嵌套必炸,所以要其他方法

    LIS

    然后考试也没想到lower_bound去做LIS
    考后,个人认为这里的转换很巧妙

    将当前这个数可以连接的另一行的数的位置依次存入t数组内

    由于连接的线段不相交,所以从前往后必定严格上升

    这不难想到可以用LIS
    把当前这个数可以连接的另一行的数的位置依次存入t数组内

    为了不让这个数同时连另一行的多个数
    所以依次存入t数组从大到小排序,用sort+cmp重载运算符

    最后lower_bound求t数组的最长上升子序列即可

    #include<bits/stdc++.h>
    using namespace std;
    int n,ans,sum,tot;
    int a[100010],b[100100];
    int t[100010];
    int c[100];
    bool cmp(int a,int b) {
    	return a>b;
    }
    int main() {
    	//freopen("line.in","r",stdin);
    	//freopen("line.out","w",stdout);
    	cin>>n;
    	for(int i=1; i<=n; i++){
    		cin>>a[i];
    	}
    	for(int i=1; i<=n; i++) {
    		int x;
    		cin>>x;
    		b[x]=i;
    	}
    	for(int i=1; i<=n; i++) {
    		int l=0;
    		int head=max(1,a[i]-4);
    		int tail=min(n,a[i]+4);
    		for(int j=head;j<=tail;j++){
    			l++;
    			c[l]=b[j];
    		}
    		sort(c+1,c+l+1,cmp);
    		for(int j=1;j<=l;j++) {
    			if(tot==0){
    				tot++;
    				t[tot]=c[j];
    			}
    			else {
    				if(c[j]>t[tot]) {
    					tot++;
    					t[tot]=c[j];
    				}else{
    					int y=lower_bound(t+1,t+tot+1,c[j])-t;
    					t[y]=c[j];
    				}
    			}
    		}
    	}
    	cout<<tot;
    	return 0;
    }
    

    lower_bound简介

    lower_bound是STL的一个函数,也是[左闭右开)结构
    然后用的是二分查找的方法,返回的该数字的地址
    以后补LIS等题目和lower/upper_bound做法的题解

  • 相关阅读:
    预编译命令 #if DEBUG
    conda常用命令
    tensorflow 安装指南
    LocNET和池化理解
    同时安装cuda8和cuda9
    np.transpose
    python中List的slice用法
    书单
    训练工程
    linux 查看进程
  • 原文地址:https://www.cnblogs.com/pqh-/p/13928670.html
Copyright © 2011-2022 走看看