HDU 4268 - Alice and Bob

本文介绍了一道经典的博弈论问题,通过使用贪心算法和multiset数据结构解决了一个关于矩形覆盖的问题。讲述了如何利用排序和二分查找来优化算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

时间限制:10.000秒(JAVA)/5.000秒(其他语言)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4268


  组队赛秃头了……

  当时一晚上死磕的就是这道题,结果到最后也没做出来。看了别人的代码之后有种恍然大悟的感觉,看来思路还是不够开阔啊……

  一说“Alice and Bob”八成就是博弈了。题意倒是挺简单,就是输入Alice和Bob的n个矩形的高和宽,当一个矩形高和宽均大于等于另一个矩形的时候,那么这个矩形可盖住该矩形,问Alice最多可以盖住Bob多少个矩形。

  

  可以说是个贪心吧,每次用Alice的一个矩形盖住它能够盖住的最大矩形。自然而然地想到在输入之后要对两个人的矩形进行排序,然后在排好序的结构内二分查找,这是一开始的想法。然而,这题比较麻烦的地方是,排序是先按高再按宽排序或者反过来,然而判断是否盖住需要的是高和宽均大于另一个矩形。比赛的时候就是因为这个问题没有处理好,一开始答案错误,后来超时……

  正解则用到了multiset——多重集合容器,天生有序并且允许元素重复。开始将Alice和Bob的矩形全部排好序,排序方式是先高后宽。然后Alice的矩形从小到大挑,每次选一个后将Bob的矩形中高小于等于该矩形的矩形的宽全部放进集合(注意:不是从头开始放,而是从上一次放过的位置继续,具体可见代码),然后再用upper_bound查找(upper_bound找到的是大于传入参数的第一个元素的位置),根据返回的位置判断是否有能够盖住的矩形,如果有,则将该宽的数据删除。因为下一次将Bob矩形放入集合的时候是从上一次放入矩形的最后一个位置向后继续放,所以每个矩形只会存入一次,不会造成重复和时间的浪费。


#include 
  
   
#include 
   
    
#include 
    
     
#include 
     
      

using namespace std;

struct rect {
    int h, w;
    bool operator < (const rect &r) const  {
        if(h != r.h) return h < r.h;
        else return w < r.w;
    }
};

const int maxn = 100010;
rect a[maxn], b[maxn];
multiset
      
        ss;

int main() {
//    freopen("in.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while(T--) {
        int N;
        scanf("%d", &N);
        for(int i = 0; i != N; ++i) scanf("%d%d", &a[i].h, &a[i].w);
        for(int i = 0; i != N; ++i) scanf("%d%d", &b[i].h, &b[i].w);

        sort(a, a + N);
        sort(b, b + N);

        ss.clear();

        int sum = 0;

        for(int i = 0, j = 0; i != N; ++i) {
            for( ; j < N && a[i].h >= b[j].h; ++j) ss.insert(b[j].w);

            multiset
       
        ::iterator p = ss.upper_bound(a[i].w); if(p != ss.begin()) { sum += 1; ss.erase(--p); } } printf("%d\n", sum); } } 
       
      
     
    
   
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值