现在有n(n<5000)个木头,每个木头都有长度l和重量w(l<10000,w<10000),现在你要对木头进行加工:
1.第一根木头需要先花费1min;
2.加工完第i跟木头后,假设w[i+1]<=w[i]并且l[i+1]<=l[i],那么不需要准备时间;
现输入多组数据,求最小时间代价
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
Output
2
1
3
题意:求同时满足木棒的长和重量都构成不下降子序列的最少组数。
思路:显然是一个线性DP,和LIS很像,但有两个限制条件(长度和重量),我们可以先任选其中一个条件(假设长度)进行排序,此时其中长度条件已经满足,不需要再对其进行多余考虑,减轻负担,只需要对重量进行LIS即可。
代码:
1 #include<cstdio>
2 #include<iostream>
3 #include<algorithm>
4 #include<cstring>
5 using namespace std;
6
7 const int maxn=5000+100;
8
9 struct wood{
10 int l;
11 int w;
12 }line[maxn];//模拟二元组,方便排序
13 int f[maxn];//dp数组
14 int ans,n;
15 bool comp(wood a,wood b){
16 if(a.l==b.l)return a.w<b.w;
17 return a.l<b.l;
18 }
19 void Init(){
20 memset(f,0,sizeof(f));//不要忘了加cstring头文件
21 memset(line,0,sizeof(line));
22 ans=1;//一定要初始化为1,因为开始木块需要准备
23 }
24 void DP(){
25 for(int i=2;i<=n;i++){
26 f[i]=1;
27 for(int j=1;j<i;j++){
28 if(line[i].w<line[j].w && f[i]<f[j]+1){
29 f[i]=f[j]+1;
30 ans=max(ans,f[i]);
31 }
32 }
33 }
34 printf("%d
",ans);
35 }
36 int main(){
37 int t;cin>>t;
38 for(int i=1;i<=t;i++){
39 Init();//初始化
40 scanf("%d",&n);
41 for(int j=1;j<=n;j++){
42 scanf("%d%d",&line[j].l,&line[j].w);
43 f[i]=1;
44 }//填充二元组
45 sort(line+1,line+n+1,comp);//对长度排序
46 DP();
47 }
48 return 0;
49 }
![](https://img2020.cnblogs.com/blog/2053261/202006/2053261-20200601103010439-492607520.png)