题解 P1233 【木棍加工】

Guoyh

2018-12-17 22:32:02

Solution

# DP求最大上升子序列 $O(n^2)$ 算法 先根据长度从高到低排序,如果长度相同,再根据宽度从高到低排序。 如果是在同一次准备周期里面,前面的木棍一定在后面木棍之前被加工。 这样,这个问题就转化成了在 $n$ 个数中,求不上升子序列最少个数。 根据 dilworth 定理,不上升子序列最小个数等于最大上升子序列的长度。 于是乎,问题又简化成求 $n$ 个数的最大上升子序列 下面贴代码 ```cpp # include <cstdio> # include <algorithm> # define F(i, a, b) for (int i = a; i < b; i++) using namespace std; struct MG{ int l, w; bool operator < (const MG &x) const{ //重定向小于号用于排序 return l == x.l ? w > x.w : l > x.l; } } m[5050]; /* //也可以不重定向小于号,定义比较函数 bool cmp(MG x, MG y){ if (x.l != y.l) return x.l > y.l; else return x.w > y.w; } */ int f[5050]; //dp int main(){ int n, ans = 0; scanf("%d", &n); F(i, 0, n) scanf("%d%d", &m[i].l, &m[i].w); sort(m, m + n); //根据先前重定向的小于号排序 //sort(m, m + n, cmp) //如果先前定义比较函数要这样写 F(i, 0, n){ for (int j = i - 1; j >= 0; j--){ if (m[i].w > m[j].w) f[i] = max(f[i], f[j] + 1); } ans = max(ans, f[i]); //更新ans的值 } printf("%d\n", ans + 1); //加上最大上升子序列的最后一个元素 return 0; } ```