Wooden Stricks——两个递增条件的线性DP

题目

一堆n根木棍。每个棒的长度和重量是预先已知的。这些木棒将由木工机械一一加工。机器需要准备一些时间(称为准备时间)来准备处理木棍。设置时间与清洁操作以及更换机器中的工具和形状有关。木工机械的准备时间如下: 
  (a)第一个木棍的准备时间为1分钟。
  (b)在处理长度为l和重量为w的棒之后,如果l <= l'并且w <= w',则机器将不需要设置长度为l'和重量为w'的棒的设置时间。否则,将需要1分钟进行设置。
您将找到处理给定的n根木棍的最短准备时间。例如,如果您有五根长度和重量对分别为(9,4),(2,5),(1、2),(5、3)和(4,1)的摇杆,则最小设置时间应该是2分钟,因为有对(4,1),(5,3),(9,4),(1,2),(2,5)对的序列。

输入值

输入包含T个测试用例。在输入文件的第一行中给出了测试用例的数量(T)。每个测试用例由两行组成:第一行具有整数n,1 <= n <= 5000,代表测试例中木棍的数量,第二行包含2n个正整数l1,w1,l2, w2,...,ln,wn,每个大小最大为10000,其中li和wi分别是第i个木棍的长度和重量。2n个整数由一个或多个空格分隔。

输出量

输出应包含以分钟为单位的最短建立时间,每行一条。

样本输入

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 

样本输出

2
1
3


分析
首先理解题目大意,不难看出,需要求最长上升子序列,不过这道题特殊在,要维护两个条件同时递增。
既然要两个条件要同时满足,那就先预处理,使其中已经满足了一个条件,再在此基础上去考虑另一个条件不就好了吗?就是一道线性DP
代码
对数据的处理:
  (其中flag用于表示是否已经被放进了某一个子序列中)
struct node{
    int l;
    int w;
    bool flag;
}sticks[5005];

bool cmp(node a,node b){
    if(a.l!=b.l)
        return a.l > b.l;
    else
        return a.w > b.w;
}
此时已经处理好其中一项条件,再继续处理第二个条件,找出反链即可(和导弹拦截相似但并不一样,这个顺序已经固定)
        sort(sticks,sticks+n,cmp);
        int ans = 0,min;
        for(int i = 0; i < n; i++){
            if(sticks[i].flag) continue;
            min = sticks[i].w;
           for(int j = i+1; j < n; j++){
              if(min >=sticks[j].w && !sticks[j].flag){
                     min = sticks[j].w;
                     sticks[j].flag = true;
                }
            }
             ans++;
       } 
       printf("%d\n",ans);  

关键点就这些了

 

谢谢浏览

 

 

posted @ 2020-04-07 15:35  HH_Halo  阅读(159)  评论(0编辑  收藏  举报