UVa


还是贪心法。

把原始数据排序,排序的规则是先依照右端点排序,右端点同样的情况下,再依照左端点排序。然后最左边開始遍历线段,取第一个线段的右端点,推断是否和第二个线段的右端点相等。假设相等,肯定能够缩短为两个相邻的。假设不想等。再推断第一个右端点是否小于第二个左端点,假设小于,则中间肯定有空隙,标记加1。然后在拿第二个的右端点和第三个线段继续同理比較;假设大于,则说明第二个的能够紧邻放在第一个的最右边。相当于把第一个线段放大,这里就是贪心的思想了。

PS:刚開始写cmp函数不小心写了引用,直接CE了一把。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <stack>
#include <queue>
#include <bitset> 
#include <cassert> 
#include <cmath>
#include <functional>

using namespace std;

typedef pair<int, int> Pair;

int n;

// 先依照右端点从小到大排序,右端点同样的情况下按左端点排序
bool cmp(Pair A, Pair B)
{
	if (A.second != B.second) {
		return A.second < B.second;
	}
	return A.first < B.first;
}

int main()
{
	ios::sync_with_stdio(false);
	int T;
	cin >> T;
	while (T--) {
		cin >> n;
		vector<Pair> A;
		int x, y;
		for (int i = 0; i < n; i++) {
			cin >> x >> y;
			A.push_back(Pair(x, y));
		}
		sort(A.begin(), A.end(), cmp);

		// 贪心求解
		int ret = 1, right = A[0].second;
		for (int i = 1; i < n; i++) {
			if (right != A[i].second) {
				if (right < A[i].first) {
					ret++;
					right = A[i].second;
				}
				else {
					right++; // 这里就是贪心处理
				}
			}
		}
		cout << ret - 1 << endl;
	}

	return 0;
}




原文地址:https://www.cnblogs.com/mfmdaoyou/p/7052685.html