根据每根棍子有长与重 首先想到了坐标轴上点的横纵坐标

这样该问题就可以抽象为 类似于拦截导弹问题的最长严格升或降子序列问题

 

这里l为x w为y

先将所有坐标平面上的点按横坐标从小到大排序 相等则按纵坐标从小到大排序

这样 问题中的两个要求 li<=lj 与 wi<=wj 已满足第一项 再通过求最长严格降子序列得出答案

 

首先我们正向考虑

应该从x最小的点开始向x轴正方向找 遇到一个y值更大的点(x值根据排序 已保证递增) 则说明这两个点 即这两根木棍可以放到一个批次处理

由此我们可以得出 每一个批次的木棍中 最后一根木棍(设为p)的长度与重量(x与y)都是最大的 并且再没有长度与重量都大于等于木棍p的其他木棍

而根据我们的排序 若stick[p]后还有元素存在 说明该木棍长度(x)大于等于木棍p 但是重量(y)小于木棍p 因此只能下一批次处理

以上就是我们为什么可以通过求最长降子序列来求解 我们所求的最长降子序列中的每一个元素其实就是每一个批次的最后一根木棍

 

#include <stdio.h>
#include <algorithm>
using namespace std;

struct node
{
int x;
int y;
};

node stick[5010];
int num[5010];
int n;

int cmp(node n1,node n2)
{
if(n1.x==n2.x)
{
return n1.y<n2.y;
}
else
{
return n1.x<n2.x;
}
}

int main()
{
int t,i,j,maxx,ans;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d",&stick[i].x,&stick[i].y);
}
sort(stick+1,stick+n+1,cmp);
for(i=1;i<=n;i++)
{
num[i]=1;
}
ans=0;
for(i=n;i>=1;i--)
{
maxx=0;
for(j=i+1;j<=n;j++)
{
if(stick[i].y>stick[j].y&&num[j]>maxx)
{
maxx=num[j];
}
}
num[i]=maxx+1;
if(num[i]>ans) ans=num[i];
}
printf("%d\n",ans);
}
return 0;
}