HDU基本最*子序列集锦1

最大连续子序列(HDU1003,1231)

最大递增子序列和,sum[i]=max(sum[j])+a[i],j<=i(HDU1087)。

最长公共子序列,LCS经典算法(HDU1159)。

题解:

实际上,我没看出hdu1003和1231的本质差别,形式上的差别就是记载的东西不一样,一个是记载下标,一个是记载元素。基本就是那么回事吧。很多算法书在讨论时效都会拿这个例子来说明,让大家看到算法的力量,从一个弱渣算法到O(n)的过程。

大概思路就是,基础dp吧。至于用数组存起来是实在没有必要的。

HDU1231

/***********************************************************
	> OS     : Linux 3.2.0-60-generic #91-Ubuntu
	> Author : yaolong
	> Mail   : [email protected]
	> Time   : 2014年05月30日 星期五 07:28:17
 **********************************************************/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
int main(){

    int k;

    while(scanf("%d",&k)&&k){

        int res=-1,sum=0,ans_i,ans_j;
        int tmp,sb_i,sb_j;
        int tmp_i=0,tmp_j=0;
        for(int i=1;i<=k;i++){
            scanf("%d",&tmp);
            if(sum<=0){ //当前和小于等于0,更新当前和为tmp,起始也记做tmp
                sum=tmp;
                tmp_i=tmp;
            }else{      //否则加上新的。
                sum+=tmp;
            }
            if(sum>res){ //当其比较大的时候,更新。
                res=sum;
                ans_i=tmp_i;
                ans_j=tmp;
            }
            if(i==1){  //为了全负数的情况,要记下第一个和最后一个。
                sb_i=tmp;
            }else if(i==k){
                sb_j=tmp;
            }
        }

        if(res<0){ //我们初始化的是-1,如果sum不是大于等于0,是不会更新,也就是res<0输出特殊情况即可。

            printf("%d %d %d\n",0,sb_i,sb_j);
        }else{  //正常情况
            printf("%d %d %d\n",res,ans_i,ans_j);
        }
}
}

HDU1003

/***********************************************************
	> OS     : Linux 3.2.0-60-generic #91-Ubuntu
	> Author : yaolong
	> Mail   : [email protected]
	> Time   : 2014年05月30日 星期五 08:56:52
 **********************************************************/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
int main(){
    int k;
    int T,p=1;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&k);
        int res=-12345678,sum=0,ans_i,ans_j;
        int tmp_i=1,tmp_j=1,tmp;
        for(int i=1;i<=k;i++){

            scanf("%d",&tmp);
            if(sum<0){
                sum=tmp;
                tmp_i=i;
            }else{
                sum+=tmp;
            }
            if(sum>res){
                 res=sum;
                 ans_i=tmp_i;
                 ans_j=i;
            }

        }
        if(p>1){
            puts("");
        }
        printf("Case %d:\n",p++);
        printf("%d %d %d\n",res,ans_i,ans_j);
    }
    return 0;

}

HDU1087

题目意思就是找最大的递增子序列和,比如1 3 2 3 4 其最大递增子序列和为1 +2+3+4=10。

/***********************************************************
> OS     : Linux 3.2.0-60-generic #91-Ubuntu
> Author : yaolong
> Mail   : [email protected]
> Time   : 2014年05月29日 星期四 07:12:52
**********************************************************/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
int v[1234],sum[1234];
int main(){
    int N;
    while(cin>>N&&N){
        for(int i=1;i<=N;i++){
            cin>>v[i];

        }
        memset(sum,0,sizeof(sum));
        sum[0]=0;
        v[0]=0;
        int ind;
        for(int i=1;i<=N;i++){
            for(int j=0;j<i;j++){
                if(v[j]<v[i]){
                    sum[i]=max(sum[i],sum[j]+v[i]);
                }
            }
        }
        int max=v[0];
        for(int i=1;i<=N;i++){
            if(sum[i]>max){
                max=sum[i];
                //cout<<i<<" "<<max<<endl;

            }
        }
        cout<<max<<endl;
    }
    return 0;

}

HDU1159最长公共子序列(LCS)

这个是经典的动态规划教材案例啦,就不多说了。

/***********************************************************
> OS     : Linux 3.2.0-60-generic #91-Ubuntu
> Author : yaolong
> Mail   : [email protected]
> Time   : 2014年05月29日 星期四 08:57:12
**********************************************************/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
string str1,str2;
int dp[500][500];
int LCS(){
    int n=str1.length();
    int m=str2.length();
    for(int i=0;i<=n;i++){
        dp[i][0]=0;

    }
    for(int i=0;i<=m;i++){
        dp[0][i]=0;

    }
    //  cout<<n<<m<<endl;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(str1[i-1]==str2[j-1]){
                //cout<<str1[i]<<" "<<str2[j]<<endl;
                dp[i][j]=dp[i-1][j-1]+1;

            }else{
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);

            }

        }

    }
    return dp[n][m];

}
int main(){
    while(cin>>str1>>str2){
        //cout<<str1<<" "<<str2<<endl;
        cout<<LCS()<<endl;

    }

}

HDU基本最*子序列集锦1

时间: 2024-10-17 13:24:16

HDU基本最*子序列集锦1的相关文章

hdu 1068 最大子序列和变形,,,

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 200 using namespace std; struct node { int x,y,z; }; int cmp(node a,node b) { if(a.x==b.x) return a.y<b.y; return a.x<b.x; } int mymax(int

HDU 1003 Max Sum【动态规划求最大子序列和详解 】

Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 250714    Accepted Submission(s): 59365 Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max su

hdu 1087 Super Jumping! Jumping! Jumping!(最大上升子序列和)

Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 36986    Accepted Submission(s): 16885 Problem Description Nowadays, a kind of chess game called “Super Jumping!

HDU 5316 Magician(线段树区间合并, 子序列最值 多校2015啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5316 Problem Description Fantasy magicians usually gain their ability through one of three usual methods: possessing it as an innate talent, gaining it through study and practice, or receiving it from an

hdu 1159 Common Subsequence(最长公共子序列 DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1159 Common Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 25416    Accepted Submission(s): 11276 Problem Description A subsequence of

HDU 1231 最大连续子序列 DP题解

典型的DP题目,增加一个额外要求,输出子序列的开始和结尾的数值. 增加一个记录方法,nothing special. 记录最终ans的时候,同时记录开始和结尾下标: 更新当前最大值sum的时候,更新开始节点. const int MAX_N = 10001; long long arr[MAX_N]; int N, sta, end; long long getMaxSubs() { long long sum = 0, ans = LLONG_MIN; int ts = 0; for (int

HDU 1087 &amp;&amp; POJ 2533(DP,最长上升子序列).

~~~~ 两道题的意思差不多,HDU上是求最长上升子序列的和,而POJ上就的是其长度. 貌似还有用二分写的nlogn的算法,不过这俩题n^2就可以过嘛.. ~~~~ 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1087 http://poj.org/problem?id=2533 ~~~~ HDU1087: #include<cstdio> #include<cstring> #include<algorithm> #

HDU 3998 Sequence(经典问题,最长上升子序列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3998 解题报告:求一个数列的最长上升子序列,并求像这样长的不相交的子序列最多有多少个. 我用的是最简单的方法,就是每次求最长上升子序列,然后每次将求得的子序列从数列里面删掉,然后再对剩下的数列求最长上升子序列,如果求得的子序列的长度比第一次求得的长度小的话,就退出.不过我这题卡了很久,原因就是因为用这种方法求的过程中,用到了很多变量,但是没有注意每一步求最长上升子序列的时候都要进行初始化,哎. Vi

[ACM] hdu 1231 最大连续子序列 (动规复习)

最大连续子序列 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 17687    Accepted Submission(s): 7828 Problem Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j