hdu 1423+hdu 4512 最长公共递增子序列

hdu1423 是 最长公共递增子序列的一个基本题   hdu 4512 是一个变式

基本算法就是 结合最长公共子序列和最长递增子序列 的算法。

附: 最长递增子序列:http://blog.csdn.net/techmonster/article/details/49515587  最长公共子序列+变式:http://blog.csdn.net/techmonster/article/details/49976889

结合以下代码应该能明白 最长公共递增子序列 的算法。


然后说 hdu 4512 。我们把一个数组当作两个来看。比较慢的算法是,枚举排队在中间的人,左边作为一个数组右边作为一个数组。这样效率较低。

我们采取的方法是,枚举右边数组的最后一个数的位置,从左往右。具体看代码注释

#include<cstdio>//*****hdu 1423******  <span style="font-family: Arial, Helvetica, sans-serif;">*****hdu 1423******   </span><span style="font-family: Arial, Helvetica, sans-serif;">*****hdu 1423******</span>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<queue>
#define MS(x,y) memset(x,y,sizeof(x))
#define pi acos(-1.0)
using namespace std;
void fre(){freopen("t.txt","r",stdin);}
typedef long long LL;
typedef unsigned long long ULL;
const int MOD = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int MAXN = 4*(1e5)+1;
const int eps = -(1<<30);

int main()
{
   // fre();
    int t,n,m,dp[505];
    int i,j,a[505],b[505];
    scanf("%d",&t);
    while(t--)
    {
        MS(dp,0);
        scanf("%d",&n);//read
        for(i = 1; i <= n; ++i) scanf("%d",&a[i]);
        scanf("%d",&m);
        for(i = 1; i <= m; ++i) scanf("%d",&b[i]);
        for(i = 1; i <= n; ++i)//solve
        {
            int len = 0;
            for(j = 1; j <= m; ++j)
            {
                if(a[i] > b[j])len = max(len,dp[j]);
                else if(a[i] == b[j]) dp[j] = max(dp[j],len+1);
            }
        }
        int ans = -1;
        for(i = 1; i <= m; ++i) if(ans < dp[i]) ans = dp[i];//search
        printf("%d\n",ans);
        if(t!=0) printf("\n");
    }
    return 0;
}

#include<cstdio>//********hdu 4512**********
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<queue>
#define MS(x,y) memset(x,y,sizeof(x))
#define pi acos(-1.0)
using namespace std;
void fre(){freopen("t.txt","r",stdin);}
typedef long long LL;
typedef unsigned long long ULL;
const int MOD = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int MAXN = 4*(1e5)+1;
const int eps = -(1<<30);

int main()
{
  //  fre();
    int t,n,m,dp[205],loc[205];//loc表示左边某个士兵队友身高相等的右边士兵的位置
    int i,j,a[205];
    scanf("%d",&t);
    while(t--)
    {
        MS(dp,0);
        scanf("%d",&n);
        for(i = 1; i <= n; ++i) scanf("%d",&a[i]);//read

        for(i = n; i >= 1; --i) //solve  ,枚举右边序列的最后一个数的位置,对于i=k,i<k时计算的情况都仍然可用(想想为什么),因此直接计算。
        {
            int len = 0;
            for(j = 1; j < i; ++j)//遍历左边序列
            {
                if(a[i] > a[j]) len = max(len,dp[j]);
                else if(a[i] == a[j])
                {
                    if(len+1>dp[j])//此处必须用>,用>= 是错误的,因为身高相等的不一定只有两个,我们必须选择距离远的两个人
                    {
                        loc[j] = i;
                        dp[j] = len+1;
                    }
                }
            }
        }

        int maxx = 1;
        for(i = 1; i <= n; ++i)//search
        {
            if(dp[i]*2 >= maxx)//pay attention to "*2",此处必须用 >=。
            {
                maxx = dp[i]*2;
                for(j = i; j < loc[i]; ++j)
                {
                    if(a[j]>a[i])
                    {
                        maxx++;
                        break;
                    }
                }
            }
        }
        printf("%d\n",maxx);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值