线性动归之Wooden Sticks

题面:现在有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\n",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 }

 

posted @ 2020-04-07 13:34  sodak  阅读(206)  评论(0编辑  收藏  举报