题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4268
一般像这种题目,首先会想到动态规划算法但是这个题目一看数据就想到肯定是要找一个O(n)的或者O(n*logn)的一个算法,所以动态规划这种
算法比较难找,也很少见这种低复杂度的动态规划算法,所以就只能是贪心能提供这种复杂度了。
把两个人的牌揉到一起,做个标记是alice的还是bob的,然后按照长排序,长相等按照宽排序,都相等就alice在后bob在前面
然后从前向后遍历,如果是bob的,直接将bob的宽插入的set中,如果是alice,则让alice的这张牌去覆盖set里面比alice的宽
小或相等的最大的宽,然后从set中删除,这里为什么宽符合条件就能覆盖呢,因为前面按照长从小到大排序了,所以说这个
是一个很明显的贪心!
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <set>
using namespace std;
#define maxn 110000
struct point
{
int length;
int width;
int first;
}po[maxn*2];
int n;
multiset<int> my_set;
bool cmp(const point &a,const point &b)
{
if(a.length == b.length)
{
if(a.width == b.width)
return a.first < b.first;
return a.width < b.width;
}
return a.length < b.length;
}
multiset<int>::iterator it;
int find_ans()
{
int ans=0,i,j,k;
for(i=0;i<n;i++)
{
if(po[i].first==0)
my_set.insert(po[i].width);
else
{
if(!my_set.empty() && *my_set.begin() <= po[i].width)
{
it=my_set.upper_bound(po[i].width);
it--;
my_set.erase(it);
ans++;
}
}
}
return ans;
}
int main()
{
int t,i,j,k;
scanf("%d",&t);
while(t--)
{
my_set.clear();
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&po[i].length,&po[i].width);
po[i].first=1;
}
n*=2;
for(i;i<n;i++)
{
scanf("%d%d",&po[i].length,&po[i].width);
po[i].first=0;
}
sort(po,po+n,cmp);
printf("%d\n",find_ans());
}
return 0;
}