• 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
    ",ans);
    42     }
    43     return 0;
    44 }
    
    
    


  • 相关阅读:
    POJ3352 Road Construction (双连通分量)
    强连通分量(模板)
    图基本概念
    Air Raid(最小路径覆盖)
    Machine Schedule(最小覆盖)
    hdoj 1564 Play a game
    nyoj 483 Nightmare【bfs+优先队列】
    hdoj 1083 Courses【匈牙利算法】
    hdoj 2036 改革春风吹满地
    nyoj 353 3D dungeon
  • 原文地址:https://www.cnblogs.com/Siegfried-L/p/12652800.html
Copyright © 2020-2023  润新知