zoukankan      html  css  js  c++  java
  • 洛谷 P1233 【木棍加工】题解

    算法:排序,DP(最长上升子序列)

    前言:

    此题的数据非常水,这里给予一组 hack 数据:

    21
    96 25 1 9 39 19 87 51 7 61 11 1 46 74 51 1 1 61 51 84 51 76 49 33 13 57 73 86 41 99 9 81 41 51 13 61 17 33 81 62 47 41 

    请求加强数据!

    ------------

    正文

    我看题解里好多人写的都是贪心,唯一一个赞比较多的 DP 解法还被我的数据 hack 了,于是就写了这篇题解(其实我第一次提交的代码也会被 hack)。

    这道题首先要用结构体排序,以木棍的长度为第一关键字(从大到小),以宽度为第二关键字排序(同样也是从大到小)。

    需要注意的是,如果在两根木棍长度相等的情况下,必须要按宽度排序,否则就会被 hack。

    在排序后,我们直接可以扔到这个长度不管了,直接把宽度跑一遍最长不上升子序列,得出最长不上升子序列的个数。但是我们知道,最长不上升子序列的个数等于最长上升子序列的长度,所以我们只需要求出后者即可。

    $ m code $

    # include <bits/stdc++.h>
    using namespace std;
    # define maxN 50005
    struct Stick {
        int l, w;
    }stick[maxN];
    // 首先定义一个名字为 Stick 的结构体,存放木棍的长度和宽度.
    int n, dp[maxN];
    // 然后定义木棍的数量 n 和 dp 数组.
    bool cmp(Stick, Stick);
    // 这是排序函数.
    int main() {
    //    freopen("1.in", "r", stdin);
        cin >> n;
        for(int i = 1; i <= n; ++i) cin >> stick[i].l >> stick[i].w;
        sort(stick + 1, stick + 1 + n, cmp);
        // 输入数据,排序.
        dp[1] = stick[1].w;
        // dp 数组的初始化.
        int k = 1; // 答案最小也为 1.
        for(int i = 2, j; i <= n; ++i) j = lower_bound(dp + 1, dp + k + 1, stick[i].w) - dp, j <= k ? dp[j] = stick[i].w : dp[++k] = stick[i].w;
        //跑一遍最长上升子序列.
        cout << k << '
    ', exit(0);
        // 输出答案.
    }
    bool cmp(Stick a, Stick b) {
        if(a.l != b.l) return a.l > b.l; // 如果两根木棍的长度不等,那么按木棍的长度从大到小排序.
        return a.w > b.w; // 否则按木棍的宽度从大到小排序.
    }
  • 相关阅读:
    hdu5360 Hiking(水题)
    hdu5348 MZL's endless loop(欧拉回路)
    hdu5351 MZL's Border(规律题,java)
    hdu5347 MZL's chemistry(打表)
    hdu5344 MZL's xor(水题)
    hdu5338 ZZX and Permutations(贪心、线段树)
    hdu 5325 Crazy Bobo (树形dp)
    hdu5323 Solve this interesting problem(爆搜)
    hdu5322 Hope(dp)
    Lightoj1009 Back to Underworld(带权并查集)
  • 原文地址:https://www.cnblogs.com/Xray-luogu/p/11006416.html
Copyright © 2011-2022 走看看