题意
有N根木棍等待处理。机器在处理第一根木棍时需要准备1分钟,此后遇到长宽都不大于前一根木棍的木棍就不需要时间准备,反之则需要1分钟重新准备。比如木棍按照(3,3)、(1,3)、(1,4)、(2,3)的顺序进入,共需要准备3分钟
Input
第一行是T,表示测试数据个数。测试数据的第一行是N(1 <= N <= 5000)此后一行是 l1 , w1 , l2 , w2 ,..., ln , wn......长宽都小于10000
Output
每个一行,表示最短准备时间
Sample Input
3 5 4 9 5 2 2 1 3 5 1 4 3 2 2 1 1 2 2 3 1 3 2 2 3 1
Sample Output
2 1 3
题解:
本题用到一个定理:不上升子序列的最小划分数=最长上升子序列的长度。可以由题意知若准备时间最短,则就是求按木板的某个属性求其不上升子序列的最小划分数。我们可以先对木板按其宽w从小到大排序,然后根据长l求其最长上升子序列的长度(倒着求),则答案就是这个长。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=5e3+3;
struct W{
int l,w;
bool operator < (const W &t) const {
if(w < t.w) return true;
else if(w == t.w && l < t.l) return true;
return false;
}
}a[N];
int dp[N],n;
int main(){
int t;
cin>>t;
while(t--){
cin>>n;
for(int i=0;i<n;i++) scanf("%d%d",&a[i].l,&a[i].w);
memset(dp,0,sizeof(dp));
sort(a,a+n);
int cnt=0;
//和从n-1到0求最长上升子序列一样
for(int i=0;i<n;i++){
dp[i]=1;
for(int j=0;j<i;j++){
if(a[j].l>a[i].l)
dp[i]=max(dp[i],dp[j]+1);
cnt=max(cnt,dp[i]);
}
}
cout<<cnt<<endl;
}
return 0;
}