【newbie】【hdu4268】最多矩阵覆盖个数

【新手记录】

// 2016-5-4 16:30:29

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4268


/*

贪心法

 

题目:

         用A的矩阵去覆盖B的矩阵,矩阵有height,weight

         矩阵不能旋转,

         每个矩阵只能用一次,

         问最多能用A覆盖B几个

         A:o o o o o

         B:* * * * *

 

思路:

         覆盖也就是保证A.h>= B.h && A.w >= B.w

         分两步去满足条件,1#满足h, 2#满足w

         1#对A,B的矩阵按h从小到大排序,h相同的按w从小到大排序

         2#

            1> 对Ai矩阵找出所有的Bj矩阵满足, Ai.h>= Bj.h, 构成集合set, 然后选取Ai去覆盖Bj.w最大的Bj

            2> 因为Ai+1.h >= Ai.h, 所以Ai+1.h >= 之前的Bj.h, 继续添加新的Bj进set里,继续选择Ai+1去覆盖Bj.w最大的Bj,

            3> 迭代即可

         关键点

         1#找出Ai.h >= Bj.h 的Bj

         2#Ai.h >= Bj.h 则 Ai+1.h >= Bj.h

 

总结:

T<=40, N<=10^5,

即使O(n^2)复杂度, 10^10也超时间了。

 

A: o o o o o

B: * * * * *

B的全排列种可能,然后A去覆盖B,看能覆盖几个,O(n!),则应该考虑是动态规划问题

又即使O(n^2)复杂度, 10^10也超时间了,故考虑是贪心问题。

 

实现:

         O(n^2)

         1》遍历Bi,去找最小的Aj,Aj能覆盖Bi,

 

         O(n)

         2》遍历Ai, 去找最大的Bi, 利用

                   1#找出Ai.h >= Bj.h 的Bj

                   2#Ai.h >= Bj.h 则 Ai+1.h >= Bj.h

 

时间复杂度分析:

N = 10 ^5,

O(n^2)都TLE了,只能O(nlgn),O(n)这种级别

 

用到:

multiset,集合的用法

*/

// 2016-5-4 15:02:04
#include<stdio.h>
#include<set>
#include<algorithm>
using namespace std;

struct Node {
	int h;
	int w;
};

bool cmp(const Node n1, const Node n2) {
	if (n1.h != n2.h) {
		return n1.h < n2.h;
	} else {
		return n1.w < n2.w;
	}
}

Node aNode[100001];
Node bNode[100001];
multiset<int> mySet;
multiset<int>::iterator it;

int main() {
	int t, n;
	int i, j;
	scanf("%d", &t);
	while (t--) {
		scanf("%d", &n);
		for (i = 0; i < 2 * n; i++) {
			int h, w;
			scanf("%d", &h);
			scanf("%d", &w);
			if (i < n) {
				aNode[i].h = h;
				aNode[i].w = w;
			} else {
				bNode[i - n].h = h;
				bNode[i - n].w = w;
			}
		}
		sort(aNode, aNode + n, cmp);
		sort(bNode, bNode + n, cmp);

		int ans = 0;
		j = 0;
		mySet.clear();
		for (i = 0; i < n; i++) {
			while (j < n && aNode[i].h >= bNode[j].h) {
				mySet.insert(bNode[j].w);
				j++;
			}
			if (mySet.empty()) continue;
	
			it = mySet.upper_bound(aNode[i].w);
			if (it != mySet.begin()) it--;
			if (*it <= aNode[i].w) {
				mySet.erase(it);
				ans++;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}




你可能感兴趣的:(ACM,HDU,RunnngZ)