其他分享
首页 > 其他分享> > POJ 1065

POJ 1065

作者:互联网

POJ 1065

贪心、偏序集、Dilworth定理、最长下降子序列

说到偏序集,在离散里的定义是:
设R为非空集合A上的关系,如果R是自反的、反对称的和传递的,则称R为A上的偏序关系,简称偏序,记作≤。

说明 题目给出的 (L1, W1)<=(L2, W2) 是满足偏序关系的,那么本题所求的以 <= 连接的最少划分数, 就等于 < 连接的最长子序列。

解法中先进行了排序,保证按照序列顺序比较时 L 这一维度不会成为 “满足偏序关系” 这一要求的负担,可以只关注于 w 这一维度。

以上是复杂的证明,解法很简答:
1, 双关键字排序、
2, 按照 w 维度求最长下降子序列的长度。

总结:Dilworth定理:

#include <bits/stdc++.h>
using namespace std;

const int N = 1e4 + 10;

int T;
int n;
struct STICK {
	int l, w;
} stick[N];
int dp[N];

bool cmp(STICK a, STICK b) {
	if (a.l == b.l)
		return a.w < b.w;
	return a.l < b.l;
}

int main() {
	scanf("%d", &T);
	while (T--) {
		scanf("%d", &n);
		for (int i = 0; i < n; i++) {
			scanf("%d %d", &stick[i].l, &stick[i].w);
		}

		sort(stick, stick + n, cmp);
		// 不能每次初始化所有的数组,n^2的复杂度会超时
		memset(dp, -1, n * sizeof(int));

		// 通过排序将问题转化为一维最长下降子序列问题。
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j ++) {
				if (j == 0 || dp[j - 1] > stick[i].w) {
					dp[j] = max(dp[j], stick[i].w);
				}
			}
		}
		cout << lower_bound(dp, dp + n, -1, greater<int>()) - dp << endl;

	}

	return 0;
}

对于DP过程优化的写法:

for (int i = 0; i < n; ++i)
{
	*lower_bound(dp, dp + n, stick[i].second, greater<int>()) = stick[i].second;
}

参考了以下两个博客:
https://blog.csdn.net/u011008379/article/details/50725927
https://www.hankcs.com/program/cpp/poj-1065-wooden-sticks.html

标签:偏序,关系,int,1065,++,POJ,stick,dp
来源: https://www.cnblogs.com/superPG/p/16260998.html