【HDOJ 4268】 Alice and Bob (排序+二分)

【HDOJ 4268】 Alice and Bob

AB各有一组 每张牌有各自的长和宽 如果一张牌长宽都>=另一张牌 这张牌就可以覆盖另一张 问A中最多多少张牌覆盖B中的牌 每张牌都一一对应 一张只能覆盖一张也只能被一张覆盖

我们先选择一种排序方式 我先将B按长由大到小第二层按宽由大到小排序 A也同样 枚举B中卡牌 每枚举一个就把A中长>=该卡牌的卡牌的宽加入到一个可重容器multiset中 容器按一种方式排序 然后二分B该卡牌宽度 如果有就二分选择能覆盖B的最窄的

最优原因:这样枚举时容器中所有A高度肯定大于剩下的B 并且剩下的A高度小于当前枚举的B 在容器中高度就不再是选择条件 多余的高度也就没有了意义 这样只要让宽度消耗最少 肯定是最优 二分找满足的最窄的即可


代码如下:


#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
#include <list>
#include <stack>
#include <vector>
#include <set>
#include <ctime>
#include <cmath>
#include <bitset>

using namespace std;
#define STD_REOPEN() freopen("../in.in","r",stdin)
#define STT_REOPEN() freopen("../in.in","w",stdout)
#define INF 0x3f3f3f3f
#define _INF 63
#define eps 1e-4
#define ll long long
#define sc "%lld"
#define pr pair<int,int>
#define mod
#define sz
using namespace std;

typedef struct PK
{
	int h,w;
	bool operator < (const struct PK a)const//高度为首要条件 宽度为第二条件
	{
		return h == a.h? w > a.w: h > a.h;
	}
}PK;

PK a[100000],b[100000];
multiset <int> s;

int main()
{
    int n,i,x,j,cnt,t;
    multiset <int>::iterator it;
    scanf("%d",&t);
    while(t--)
	{
		scanf("%d",&n);
		s.clear();

		for(i = 0; i < n; ++i) scanf("%d %d",&a[i].h,&a[i].w);
		for(i = 0; i < n; ++i) scanf("%d %d",&b[i].h,&b[i].w);
		sort(a,a+n);
		sort(b,b+n);

		for(i = j = cnt = 0; i < n; ++i)
		{
			while(j < n && a[j].h >= b[i].h)
			{
				s.insert(a[j].w);
				++j;
			}

			it = s.lower_bound(b[i].w);

			if(it!=s.end())
			{
				cnt++;
				s.erase(it);
			}
		}
		printf("%d\n",cnt);
	}
    return 0;
}


你可能感兴趣的:(排序+二分)