• (动态规划整理)


           这一篇博客以一些OJ上的题目为载体。整理一下动态规划(DP)的应用



       一、利用动态规划来解决最长公共子序列(LCS)问题
        1、NYOJ 36  最长公共子序列
           1) 这一道题。要理解清楚状态转移方程
           
           2)回溯法求LCS的过程
          
           3)对于get()函数的理解。仅仅要你看过《算法导论》这本书,就会非常清楚为什么这样写了
       
          4)在求LCS的时候事实上还是基于遍历的思想
    /*
     * NY36_2.cpp
     *
     *  Created on: 2014年5月25日
     *      Author: pc
     */
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    
    using namespace std;
    
    const int maxn = 1005;
    
    int c[maxn][maxn];
    //返回c[i][j]。c[i][j]表示字符串a的前i个字符和字符串b的前j个字符的最长公共子序列的长度
    int get(int i,int j){
    	if(i >= 0 && j >= 0){
    		return c[i][j];
    	}
    
    	return 0;
    }
    int main(){
    	int t;
    	scanf("%d",&t);
    
    	while(t--){
    		char a[maxn];
    		char b[maxn];
    
    		memset(c,0,sizeof(c));
    
    		scanf("%s%s",&a,&b);
    
    //		gets(a);//用这样的方法会出错...我也不知道为什么
    //		gets(b);
    
    		int n = strlen(a);
    		int m = strlen(b);
    
    		int i,j;
    		for(i = 0 ; i < n ; ++i){
    			for(j = 0 ; j < m ; ++j){
    				if(a[i] == b[j]){
    					c[i][j] = get(i-1,j-1) + 1;
    				}else{
    					c[i][j] = max(get(i-1,j),get(i,j-1));
    				}
    			}
    		}
    
    		printf("%d
    ",c[n-1][m-1]);//这里之所以使用c[n-1][m-1],是由于c[n-1][m-1]已经是状态转移方程中的右下角的那一个格子了
    	}
    
    	return 0;
    }
    
    


    2、HDOJ 1159
        思想:差点儿是一模一样的题目。除了输入的处理逻辑不一样外没有什么不一样的
        
    /*
     * HDOJ_1159.cpp
     *
     *  Created on: 2014年5月25日
     *      Author: pc
     */
    
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    
    const int maxn = 1005;
    
    int c[maxn][maxn];
    int get(int i,int j){
    	if(i >= 0 && j >= 0){
    		return c[i][j];
    	}
    
    	return 0;
    }
    
    int main(){
    	char a[maxn];
    	char b[maxn];
    
    	while(scanf("%s %s",&a,&b)!=EOF){
    		memset(c,0,sizeof(c));
    
    		int n = strlen(a);
    		int m = strlen(b);
    
    		int i,j;
    		for(i = 0 ; i < n ; ++i){
    			for(j = 0 ; j < m ; ++j){
    				if(a[i] == b[j]){
    					c[i][j] = get(i-1,j-1) + 1;
    				}else{
    					c[i][j] = max(get(i-1,j),get(i,j-1));
    				}
    			}
    		}
    
    		printf("%d
    ",c[n-1][m-1]);
    	}
    
    	return 0;
    }
    

       
     3、POJ 1458(和上面的那道题一模一样)         


          二、利用动态规划(DP)来解决最长上升子序列问题(LIS)

          最长上升子序列问题的两中常见的算法:
         1)O(n^2):    我们依次遍历整个序列。每一次求出从第一个数到当前这个数的最长上升子序列,直至遍历到最后一个数字为止。然后再取dp数组里最大的那个即为整个序列的最长上升子序列。

    我们用dp[i]来存放序列1-i的最长上升子序列的长度。那么dp[i]=max(dp[j])+1,(j∈[1, i-1]); 显然dp[1]=1,我们从i=2開始遍历后面的元素即可。

          2)O(nlgn): 在从前i-1个数中找出满足a[j]<a[i](1<=j<i)条件的最大的L[j]的时间复杂度为O(n),这里採用二分查找的方法对它进行优化,使其复杂度降为O(nlogn)。
            增设一个m[]数组,m[x]存放长度为x的最长上升子序列的最小末尾数。例:m[3] = 17表示长度为3的最长上升子序列的最小末尾数为17。

          由于子序列是上升的,所以m数组中的元素有一个性质,当x<y时。m[x]<m[y]。利用这个性质来使用二分查找。
    设m数组所存储的最长上升子序列的长度为k。当前计算的数为第i个假设a[i]>m[k]。则m[++k]=a[i]。否则在m[1~k]内二分查找小于(等于)a[i]的最大值的位置p,m[p]=a[i]。
          Ex:举例:原序列为1,5,8,3。6。7  
    栈为1。5。8,此时读到3,则用3替换5。得到栈中元素为1,3,8,  再读6,用6替换8,得到1。3。6,再读7,得到终于栈为1,3,6。7  。最长递增子序列为长度4。

     

          这时候。事实上m[]就是一个记录了当中一个最长上升子序列的数组.(a[]为原始序列)

    总结的说。另外一种方法就是增设了一个m[]数组用来记录当中的一种最长上升子序列。m[i]=a表示长度为i的最长上升子序列中的末尾数是a。若当前计算到的数a[i]>m[k],则m[++k] = a[i]。否则在1~i中寻找一个合适的位置在a[i]


    1、山东理工大学OJ 1299 最长上升子序列
    题目分析:
         这道题是求最长上升子序列的长度。

    1)方法一:
    /*
     * SD_1299.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    /**
     * 该函数用于求最长上升子序列
     */
    int LIS(int a[],int n){
    
    	int dp[n+1];
    
    	int i;
    	int j;
    
    	for(i = 1 ; i <= n ; ++i){//白努力求每个索引的最长上升子序列的长度
    		int m = 0;
    
    		for(j = 1 ; j < i ; ++j){//去到当前索引i的的最长上升子序列的长度
    			if(dp[j] > m && a[i] > a[j]){
    				m = dp[j];
    			}
    		}
    
    		dp[i] = m+1;
    	}
    
    	int ans = 0;
    	for(i = 1 ; i <= n ; ++i){//其最长上升子序列的长度
    		if(dp[i] > ans){
    			ans = dp[i];
    		}
    	}
    
    	return ans;
    }
    
    int main(){
    	int n;
    	while(scanf("%d",&n)!=EOF){
    		int a[n+1];
    
    		int i;
    		for(i = 1 ; i <= n ; ++i){
    			scanf("%d",&a[i]);
    		}
    
    		int result = LIS(a,n);
    
    		printf("%d
    ",result);
    	}
    
    	return 0;
    }
    
    
    

    方法二:
    /*
     * SD_1299_Nlgn.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    
    int binary_search(int a[],int n,int t){
    	int low = 1;
    	int high = n;
    
    	while(low <= high){
    		int mid = (low+high)/2;
    
    		if(t == a[mid]){
    			return mid;
    		}else if(t < a[mid]){
    			high = mid-1;
    		}else{
    			low = mid+1;
    		}
    	}
    
    	return low;
    
    }
    
    
    int LIS_BINARY(int a[],int m[] ,int n){
    	int maxLen = 1;
    	m[maxLen] = a[1];
    
    	int i;
    	for(i = 2 ; i <= n ; ++i){
    		if(m[maxLen] < a[i]){
    			m[++maxLen] = a[i];
    		}else{
    			int p = binary_search(m,maxLen,a[i]);
    			m[p] = a[i];
    		}
    	}
    
    
    
    	return maxLen;
    }
    
    int main(){
    	int n;
    	while(scanf("%d",&n)!=EOF){
    		int a[n+1];
    		int m[n+1];
    
    		int i;
    		for(i = 1 ; i <= n ; ++i){
    			scanf("%d",&a[i]);
    		}
    
    		int result = LIS_BINARY(a,m,n);
    
    		printf("%d
    ",result);
    	}
    
    	return 0;
    }
    



    2、POJ 2533 
    题目分析:
      这一道题和上面那一道题是一样的

    3、WIKIOI 1576
    题目分析:
      这道题还是求最长上升子序列

    方法一:
    /*
     * WIKIOI_1576.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    int LIS(int a[],int n){
    	int dp[n+1];
    
    	int i;
    	int j;
    	for(i = 1 ; i <= n ; ++i){
    		int m = 0;
    
    		for(j = 1 ; j < i ; ++j){
    			if(dp[j] > m && a[j] < a[i]){
    				m = dp[j];
    			}
    		}
    
    		dp[i] = m + 1;
    	}
    
    	int ans = 0;
    	for(i = 1 ; i <= n ; ++i){
    		if(dp[i] > ans){
    			ans = dp[i];
    		}
    	}
    
    	return ans;
    }
    
    int main(){
    	int n;
    	while(scanf("%d",&n)!=EOF){
    		int a[n+1];
    
    		int i;
    		for(i = 1 ; i <= n ; ++i){
    			scanf("%d",&a[i]);
    		}
    
    		int result = LIS(a,n);
    
    		printf("%d
    ",result);
    	}
    
    	return 0;
    }
    
    



    方法二:
    /*
     * WIKIOI_1576_NLGN.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    
    int binary_search(int a[],int n, int t){
    	int low = 1;
    	int high = n;
    
    	while(low <= high){
    		int mid = (low+high)/2;
    
    		if(t == a[mid]){
    			return mid;
    		}else if(t > a[mid]){
    			low = mid+1;
    		}else{
    			high = mid-1;
    		}
    	}
    
    	return low;
    }
    
    
    int LIS_Binary(int a[],int m[],int n){
    	int maxLen = 1;
    	m[maxLen] = a[1];
    
    	int i;
    	for(i = 2 ; i <= n ; ++i){
    		if(m[maxLen] < a[i]){
    			m[++maxLen] = a[i];
    		}else{
    			int p = binary_search(m,maxLen,a[i]);
    			m[p] = a[i];
    		}
    	}
    
    	return maxLen;
    }
    
    
    int main(){
    	int n;
    	while(scanf("%d",&n)!=EOF){
    		int a[n+1];
    		int m[n+1];
    
    		int i;
    		for(i = 1 ; i <= n ; ++i){
    			scanf("%d",&a[i]);
    		}
    
    		int result = LIS_Binary(a,m,n);
    
    		printf("%d
    ",result);
    	}
    
    	return 0;
    }
    


    4、九度OJ 1533 最长上升子序列
    题目分析:这道题使用O(n^2)的算法会TLE,因此用法二来解决

    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    
    /**
     * 二分查找
     */
    int binary_search(int a[],int n, int t){
    	int low = 1;
    	int high = n;
    
    	while(low <= high){
    		int mid = (low+high)/2;
    
    		if(t == a[mid]){
    			return mid;//假设找到了返回找到的位置
    		}else if(t > a[mid]){
    			low = mid+1;
    		}else{
    			high = mid-1;
    		}
    	}
    
    	return low;
    }
    
    
    int LIS_Binary(int a[],int m[],int n){
    	int maxLen = 1;
    	m[maxLen] = a[1];
    
    	int i;
    	for(i = 2 ; i <= n ; ++i){
    		if(m[maxLen] < a[i]){
    			m[++maxLen] = a[i];
    		}else{
    			int p = binary_search(m,maxLen,a[i]);
    			m[p] = a[i];
    		}
    	}
    
    	return maxLen;
    }
    
    
    int main(){
    	int n;
    	while(scanf("%d",&n)!=EOF){
    		int a[n+1];
    		int m[n+1];
    
    		int i;
    		for(i = 1 ; i <= n ; ++i){
    			scanf("%d",&a[i]);
    		}
    
    		int result = LIS_Binary(a,m,n);
    
    		printf("%d
    ",result);
    	}
    
    	return 0;
    }
    


    5、POJ 1887 Testing the CATCHE
    题目分析:求最长非升子序列。

    这一道题与前面最大的不同就在于:求最长非升子序列。前面都是求最长上升子序列。这里用到了一个技巧:将数据保存进a[]之前。先将数据取一下反。另外还须要注意一下的就是这道题中的数据的输入的方式。其它的事实上也就没有什么了


    1)方法一:
    /*
     * POJ_1887.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    const int maxn = 1000000;
    int a[maxn];
    
    int LIS(int a[],int n){
    	int i;
    
    	int dp[n+1];
    
    	for(i = 1 ; i <= n ; ++i){
    		int m = 0;
    
    		int j;
    		for(j = 1 ; j < i ; ++j){
    			if(dp[j] > m && a[j] < a[i]){
    				m = dp[j];
    			}
    		}
    
    		dp[i] = m+1;
    	}
    
    	int ans = 0;
    	for(i = 1 ; i <= n ; ++i){
    		if(dp[i] > ans){
    			ans = dp[i];
    		}
    	}
    
    	return ans;
    }
    
    int main(){
    	int t = 0;
    
    	while(++t){
    		int temp;
    
    		int n = 0;
    		while(true){
    			scanf("%d",&temp);
    			if(temp == -1){
    				break;
    			}
    
    			a[++n] = -temp;
    		}
    
    		if(n == 0){
    			return 0;
    		}
    
    		int result = LIS(a,n);
    
    		if(t != 1){
    			printf("
    ");
    		}
    
    		printf("Test #%d:
    ",t);
    		printf("  maximum possible interceptions: %d
    ",result);
    	}
    
    	return 0;
    }
    


    2)方法二:
    /*
     * POJ_1887.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    const int maxn = 100000;
    
    int a[maxn];
    int m[maxn];
    
    int binary_search(int a[],int n,int t){
    	int low = 1;
    	int high = n;
    
    	while(low <= high){
    		int mid = (low+high)/2;
    
    		if(t == a[mid]){
    			return mid;
    		}else if(t > a[mid]){
    			low = mid+1;
    		}else{
    			high = mid-1;
    		}
    	}
    
    	return low;
    }
    
    
    int LIS_Binary(int a[],int m[],int n){
    	int maxLen = 1;
    	m[maxLen] = a[1];
    
    	int i;
    	for(i = 2 ; i <= n ; ++i){
    		if(m[maxLen] < a[i]){
    			m[++maxLen] = a[i];
    		}else{
    			int p = binary_search(m,maxLen,a[i]);
    			m[p] = a[i];
    		}
    	}
    
    	return maxLen;
    }
    
    
    int main(){
    	int t = 0;
    	while(++t){
    
    	    int n = 0;
    		int temp;
    		while(true){//特别要注意这道题的输入数据时候的方式
    			scanf("%d",&temp);
    
    			if(temp == -1){
    				break;
    			}
    
    			a[++n] = -temp;//求最长不升子序列问题的技巧...
    		}
    
    		if(n == 0){
    			return 0;
    		}
    
    
    		if(t != 1){
    			printf("
    ");
    		}
    
    		int result = LIS_Binary(a,m,n);
    
    
    		printf("Test #%d:
    ",t);
    		printf("  maximum possible interceptions: %d
    ",result);
    	}
    
    	return 0;
    }
    


    6、POJ 1631
    题目与分析:
    这道题仅仅能使用O(nlgn)算法来解决。
    /*
     * POJ_1631_nlgn.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    int binary_search(int a[],int n,int t){
    	int low = 1;
    	int high = n;
    
    	while(low <= high){
    		int mid = (low+high)/2;
    
    		if(t == a[mid]){
    			return mid;
    		}else if(t > a[mid]){
    			low = mid+1;
    		}else{
    			high = mid-1;
    		}
    	}
    
    	return low;
    }
    
    
    int LIS_Binary(int a[],int m[],int n){
    	int maxLen = 1;
    	m[maxLen] = a[1];
    
    	int i;
    	for(i = 1 ; i <= n ; ++i){
    		if(m[maxLen] < a[i]){
    			m[++maxLen] = a[i];
    		}else{
    			int p = binary_search(m,maxLen,a[i]);
    			m[p] = a[i];
    		}
    	}
    
    	return maxLen;
    }
    
    
    int main(){
    	int t;
    	scanf("%d",&t);
    
    	while(t--){
    		int n;
    		scanf("%d",&n);
    
    		int a[n+1];
    		int m[n+1];
    
    		int i;
    		for(i = 1 ; i <= n ; ++i){
    			scanf("%d",&a[i]);
    		}
    
    		int result = LIS_Binary(a,m,n);
    
    		printf("%d
    ",result);
    	}
    
    	return 0;
    }
    
    



    7、POJ 1609 Tiling Up Blocks
        题目与分析:
        这是一道二维的最长上升子序列(LIS)的问题.
         Ex:从一个样例来看题意
         (4,2),(2,4),(3,3),(1,1),(5,5)
         那么3是怎么出来的呢(1,1)->(2,4)->(5,5)
        
        方法一:
        
    /*
     * POJ_1609.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    struct Num {
    	int a;
    	int b;
    };
    
    int cmp(const void* a, const void* b) {
    	Num c = (*(Num*) a);
    	Num d = (*(Num*) b);
    
    	if (c.a != d.a) {
    		return c.a - d.a;
    	} else {
    		return c.b - d.b;
    	}
    }
    
    int LIS(Num nums[], int n) {
    	int dp[n + 1];
    
    	int i;
    	for (i = 1; i <= n; ++i) {
    		int m = 0;
    
    		int j;
    		for (j = 1; j < i; ++j) {
    			if (dp[j] > m && nums[j].a <= nums[i].a && nums[j].b <= nums[i].b) {
    				m = dp[j];
    			}
    		}
    
    		dp[i] = m + 1;
    	}
    
    	int ans = 0;
    	for (i = 1; i <= n; ++i) {
    		if (dp[i] > ans) {
    			ans = dp[i];
    		}
    	}
    
    	return ans;
    }
    
    int main() {
    	int n;
    	while (scanf("%d", &n) != EOF) {
    		if (n == 0) {
    			printf("*
    ");
    			return 0;
    		}
    
    		Num nums[n + 1];
    		int i;
    		for (i = 1; i <= n; ++i) {
    			scanf("%d%d", &nums[i].a, &nums[i].b);
    		}
    
    		qsort(nums + 1, n, sizeof(nums[1]), cmp);
    
    		int result = LIS(nums, n);
    
    		printf("%d
    ", result);
    	}
    
    	return 0;
    }
    


    8、NYOJ 79 拦截导弹


    题目与分析:
    这道题与POJ 1887是一样的。都是求最长非升子序列。

    仅仅是数据的输入方式有点不同而已。


    1)方法一
    /*
     * NJOJ_79.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    int LIS(int a[],int n){
    	int dp[n+1];
    
    	int i;
    	for(i = 1 ; i <= n ; ++i){
    		int m = 0;
    
    		int j;
    		for(j = 1 ; j < i ; ++j){
    			if(dp[j] > m && a[j] < a[i]){
    				m = dp[j];
    			}
    		}
    
    		dp[i] = m+1;
    	}
    
    	int ans = 0;
    	for(i = 1 ; i <= n ; ++i){
    		if(dp[i] > ans){
    			ans = dp[i];
    		}
    	}
    
    	return ans;
    }
    
    
    int main(){
    	int t;
    	scanf("%d",&t);
    	while(t--){
    		int n;
    		scanf("%d",&n);
    		int a[n+1];
    
    		int i;
    		for(i = 1 ; i <= n ; ++i){
    			int temp;
    			scanf("%d",&temp);
    			a[i] = -temp;
    		}
    
    		int result = LIS(a,n);
    
    		printf("%d
    ",result);
    	}
    
    	return 0;
    }
    


    2)方法二
    /*
     * NY_79_NLGN.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    
    int binary_search(int a[],int n,int t){
    	int low = 1;
    	int high = n;
    
    	while(low <= high){
    		int mid = (low+high)/2;
    
    		if(t == a[mid]){
    			return mid;
    		}else if(t > a[mid]){
    			low = mid+1;
    		}else{
    			high = mid-1;
    		}
    	}
    
    	return low;
    }
    
    int LIS_Binary(int a[],int m[],int n){
    	int maxLen = 1;
    	m[maxLen] = a[1];
    
    	int i;
    	for(i = 1 ; i <= n ; ++i){
    		if(m[maxLen] < a[i]){
    			m[++maxLen] = a[i];
    		}else{
    			int p = binary_search(m,maxLen,a[i]);
    			m[p] = a[i];
    		}
    	}
    
    	return maxLen;
    }
    
    int main(){
    	int t;
    	scanf("%d",&t);
    	while(t--){
    		int n;
    		scanf("%d",&n);
    
    		int a[n+1];
    		int m[n+1];
    
    		int i;
    		for(i = 1 ; i <= n ; ++i){
    			int temp;
    			scanf("%d",&temp);
    			a[i] = -temp;
    		}
    
    		int result = LIS_Binary(a,m,n);
    
    		printf("%d
    ",result);
    	}
    
    	return 0;
    }
    



    9、NYOJ 17 单调递增子序列

            题目与分析:
    这道题与前面的题的不同之处就在于。原始序列由数字序列变成了字符序列。

    在这样的情况下,仅仅须要办函数的參数改成char类型的即可了。

    算法的思想还是一样的。。。





    题目与分析:
    1)方法一
    /*
     * NY_17.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    int LIS(string a,int n){
    	int dp[n+1];
    
    	int i;
    	for(i = 0 ; i < n ; ++i){
    		int m = 0;
    
    		int j;
    		for(j = 0 ; j < i ; ++j){
    			if(dp[j] > m && a[j] < a[i]){
    				m = dp[j];
    			}
    		}
    
    		dp[i] = m+1;
    	}
    
    	int ans = 0;
    	for(i = 0 ; i < n ; ++i){
    		if(dp[i] > ans){
    			ans = dp[i];
    		}
    	}
    
    	return ans;
    }
    
    int main(){
    	int t;
    	scanf("%d",&t);
    	while(t--){
    		string a;
    		cin >> a;//曾经的经验,这里假设使用gets(a)会有一些问题...
    		int n = a.length();
    
    		int result = LIS(a,n);
    
    		printf("%d
    ",result);
    
    	}
    
    	return 0;
    }
    
    
    


    2)方法二:
    /*
     * NY_17_nlgn.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    
    int binary_search(string a,int n,char t){
    	int low = 0;
    	int high = n-1;
    	while(low <= high){
    		int mid = (low+high)/2;
    
    		if(t == a[mid]){
    			return mid;
    		}else if(t > a[mid]){
    			low = mid+1;
    		}else{
    			high = mid-1;
    		}
    	}
    
    	return low;
    }
    
    
    int LIS_Binary(string a,string m,int n){
    	int maxLen = 0;
    	m[maxLen] = a[0];
    
    	int i;
    	for(i = 0 ; i < n ; ++i){
    
    		if(m[maxLen] < a[i]){
    			m[++maxLen] = a[i];
    		}else{
    			int p = binary_search(m,maxLen,a[i]);
    			m[p] = a[i];
    		}
    	}
    
    	return maxLen;
    }
    
    int main(){
    	int t;
    	scanf("%d",&t);
    	while(t--){
    		string a;
    		string m;
    
    		cin >> a;
    		int n = a.length();
    
    		int result = LIS_Binary(a,m,n);
    
    		printf("%d
    ",result+1);
    	}
    
    	return 0;
    }
    




    10、NY 214
         题目分析:这道题还是求最长上升子序列的长度。由于本体的数据量比較大,用方法一的话会TLE,所以本体仅仅能用法二。


        

    方法二:
    /*
     * NY_214.cpp
     *
     *  Created on: 2014年6月4日
     *      Author: Administrator
     */
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    
    int binary_search(int a[],int n,int t){
    	int low = 1;
    	int high = n;
    	while(low <= high){
    		int mid = (low+high)/2;
    
    		if(t == a[mid]){
    			return mid;
    		}else if(t > a[mid]){
    			low = mid+1;
    		}else{
    			high = mid-1;
    		}
    	}
    
    	return low;
    }
    
    int LIS_Binary(int a[],int m[],int n){
    	int maxLen = 1;
    	m[maxLen] = a[1];
    
    	int i;
    	for(i = 1 ; i <= n ; ++i){
    
    		if(m[maxLen] < a[i]){
    			m[++maxLen] = a[i];
    		}else{
    			int p = binary_search(m,maxLen,a[i]);
    			m[p] = a[i];
    		}
    	}
    
    	return maxLen;
    }
    
    int main(){
    	int n;
    	while(scanf("%d",&n)!=EOF){
    		int a[n+1];
    		int m[n+1];
    
    		int i;
    		for(i = 1 ; i <= n ; ++i){
    			scanf("%d",&a[i]);
    		}
    
    		int result = LIS_Binary(a,m,n);
    
    		printf("%d
    ",result);
    	}
    
    	return 0;
    }
    



  • 相关阅读:
    8月8号
    8月10号
    8月5号
    8月7号
    8月4号
    8月3号。
    特殊符号 sort_wc_uniq命令 tee_tr_split命令
    管道符和作业 shell变量 环境变量
    shell 基础 history table键 通配符 输入输出重定向
    yum 源 地址的修改 源码包安装
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5142089.html
Copyright © 2020-2023  润新知