题面:现在有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 }