Vjudge_题目分享_A -> 线性Dp排列木棍 ( Dilworth定理应用

题目https://vjudge.net/contest/364177#problem/A

题目

一堆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

分析:

  
看到这道题之后第一感觉有点像友好城市。于是直接把代码直接粘了过来 仔细思考之后,发现它与友好城市的区别就在于:友好城市求的就是LIS的长度,而
此题要求的是IS的最小个数。于是我绞尽脑汁想如何用cnt来记录个数 于是我(交了两次都WA之后)想到了那个什么dilworth定理:最小划分链数=最长反链长度。
  整体思路:先将长度按从小到大排好序(结构体排序),再求排序后重量的IS最小个数。

  
再仔细观察细节,发现如下几个点需要注意: (快速!跟上思路!
  1.求的是非下降序列(即不严格的上升序列)个数,转化为求最长的严格下降序列长度。
 
2.对长度排序时,若两林昆木棍长度相等,则应让重量小的在前面,重量大的在后面。因为当长度相等时,说明这两个木棍就长度来说谁前谁后对时间无影响,
那么决定时间的唯一标准就是重量。显然,应该把重量小的放前面。
  3.多数据初始化日常坑
(我觉得这是非常非常好的几个点来

ok,用两次WA排完雷,上代码:
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 const int MAXN = 5000 + 3;
 8 
 9 int n, f[MAXN], ans, T;
10 
11 struct Match{
12     int len, wei;
13 }a[MAXN];
14 
15 bool Cmp(Match x, Match y){
16     if(x.len == y.len) return (x.wei < y.wei);//2号雷
17     return x.len < y.len;
18 }
19 
20 int main(){
21     scanf("%d",&T);
22     for(int t=1;t<=T;t++){
23         memset(f, 0, sizeof(f));//
24         memset(a, 0, sizeof(a));//
25         ans = 1;//3号雷
26         scanf("%d",&n);
27         for(int i=1;i<=n;i++){
28             scanf("%d%d",&a[i].len,&a[i].wei);
29             f[i]=1;
30         }
31         sort(a+1, a+n+1, Cmp);
32         for(int i=2;i<=n;i++){
33             f[i]=1;
34             for(int j=1;j<i;j++){
35                 if(a[i].wei<a[j].wei && f[i]<f[j]+1){//1号雷
36                     f[i] = f[j]+1;
37                     ans = max(ans, f[i]);
38                 }
39             }
40         }
41         printf("%d\n",ans);
42     }
43     return 0;
44 }

 



posted @ 2020-04-07 13:15  Sky_Sparks  阅读(226)  评论(0编辑  收藏  举报