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)对的序列。
(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 }