SPOJ 3937 - Wooden Sticks 最长上升子序列LIS

给了n个(n<=5000)木棍的长度hi与宽度wi(均小于10000),现在机器要打磨这些木棍,如果相邻连个木棍hi<=hj并且wi<=wj就不需要调整机器,问如何排序使得机器调整的次数最少。

 

【LIS】基本上和【这题】相同,但是那题中,如果hi=hj并且wi=wj长度会增加,而这道题则相反。

 

还是类似于那一题的思路:

假设wi>wj,如果hi>=hj,显然符合条件,答案不需要增加。

还是wi>wj,如果hi<hj,那么答案+1

假设wi=wj,如果hi>=hj,那么答案也是不需要增加。

 

由于要使机器调整次数尽量小,因此把w降序排列,当wi=wj时,让hi>=hj(h降序排列),然后对h求最长严格上升子序列即可。

#include<cstdio>

#include<cstring>

#include<cmath>

#include<iostream>

#include<algorithm>

#include<set>

#include<map>

#include<stack>

#include<vector>

#include<queue>

#include<string>

#include<sstream>

#define eps 1e-9

#define ALL(x) x.begin(),x.end()

#define INS(x) inserter(x,x.begin())

#define FOR(i,j,k) for(int i=j;i<=k;i++)

#define MAXN 5005

#define MAXM 40005

#define INF 0x3fffffff

using namespace std;

typedef long long LL;

int i,j,k,n,m,x,y,T,ans,big,cas,num,len;

bool flag;



struct node

{

    int s,b,i;

}p[MAXN];



int dp[MAXN];



bool cmp(node x,node y)

{

    if (x.s==y.s) return x.b>y.b;

    return x.s>y.s;

}



int main()

{

    scanf("%d",&T);

    while (T--)

    {

        scanf("%d",&n);

        

        for (i=1;i<=n;i++)

        {

            scanf("%d%d",&p[i].s,&p[i].b);

            p[i].i=i;

        }

        sort(p+1,p+1+n,cmp);

    

        num=0;

        for (i=1;i<=n;i++)//求最长上升子序列

        {

            if (p[i].b>dp[num])

            {

                dp[++num]=p[i].b;

            }else

            {

                k=lower_bound(dp+1,dp+1+num,p[i].b)-dp; 

                

                dp[k]=p[i].b;

            }

        }

        

        printf("%d\n",num);

    }

    return 0;

}

 

你可能感兴趣的:(poj)