POJ 3667 Hotel 【 set 】水法。(C++)

本文提供了一种使用pair与multiset解决POJ3667Hotel问题的方法,通过具体代码示例详细介绍了如何管理和更新空房间状态,并讨论了线段树的应用。

题目:                                                          POJ 3667 Hotel

给个链接,自己去看。

链接

大意也懒得说。

分析思路:

用 pair 加 set 。pair 装空房首位置数量。set排序加搜索位置。

pair.first 代表位置,pair.second 代表数量。

考虑到可能会出现一样的空位(其实不大可能)。用multiset,允许出现重复字符。给你们链接你们可以去看。(链接)

首先丢进去一个位置为1,数量为房间总数的pair。

​#include <iostream>
#include <cstdio>
#include <set>
using namespace std;
typedef pair<int,int> P;//习惯P表示pair

int main()
{
    multiset<P>::iterator it;
    multiset<P>::iterator its;
    multiset<P>::iterator itss;
    P p;
    int a,b;
    int d,d1,d2;
    int i=1;
    cin>>a>>b;
    {
        multiset<P> z;
        p.first=1,p.second=a;
        z.insert(p);​

 

然后,查找。

        while(b--)
        {
            scanf("%d",&d);
            if(d==1)
            {
                scanf("%d",&d1);
                d2=0;//用个标志,判断是否找得到。
                it=z.begin();
                for(; it!=z.end(); it++)
                {
                    if(it->second>=d1)
                    {
                        d2=1;//找到了。
                        break;
                    }
                }
                if(d2==0)
                    cout<<'0'<<endl;//找不到。
                else
                {
                    cout<<it->first<<endl;//找到了要处理一下。
                    p.first=it->first+d1;
                    p.second=it->second-d1;
                    z.erase(it);
                    if(p.second!=0&&p.first<=a)
                        z.insert(p);
                }
            }

然后,pair合并(空房间合并)

这个地方很麻烦。

要考虑很多。

但我自己的代码写的太多了,后来发现没有必要判断是否为end()。但懒得改了,你们可以试着去掉判断end()。

先给代码然后分析。

else if(d==2)
            {
                scanf("%d%d",&d1,&d2);
                p.first=d1;
                p.second=d2;
                it=z.lower_bound(p);
                its=it;
                itss=it;
                if(it==z.end())
                {
                    if((d1+d2-1)>=a)
                    {
                        p.second=a-d1+1;
                    }
                    if(it==z.begin());
                    else
                    {
                        it--;
                        if((it->first+it->second)>=p.first)
                        {
                            p.second=max(it->second,(p.second-it->first+p.first));
                            p.first=it->first;
                            z.erase(it);
                        }
                    }
                    if(p.second!=0&&p.first<=a)
                        z.insert(p);
                }
                else
                {
                    int i=1;
                    if(its==z.begin())
                    {
                        i=0;
                    }
                    else
                    {
                        its--;
                    }
                    while((d1+d2)>=itss->first&&itss!=z.end())
                    {
                        it=itss;
                        p.second=max(d2,(it->second+it->first-d1));
                        p.first=d1;
                        if((p.first+p.second-1)>=a)
                            p.second=a-d1+1;
                        itss=it;
                        itss++;
                        z.erase(it);
                    }
                    if(i&&(its->first+its->second)>=p.first)
                    {
                        it=its;
                    //cout<<"it->first="<<it->first<<"it->second="<<it->second<<endl;
                        p.second=max(it->second,(p.second-it->first+p.first));
                        p.first=it->first;
                        z.erase(it);
                    //cout<<"p.first="<<p.first<<"p.second="<<p.second<<endl;
                    }
                    if(p.second!=0&&p.first<=a)
                        z.insert(p);
                }
            }
        }
    }
    return 0;
}

 

分析:

第一,插入的空房间可能包括或连着后面的空房间。

第二,插入的空房间可能连着前面的空房间或者被包括。

代码懒得注释。你们可以先想想。

 

 

 

 

 

注意:

包括后面的房间,可能不是一个房间,要循环。(这里我wa了不下五次,死不信邪交了一遍一遍又一遍。)

被前面包括,只可能有一个房间,不需要循环。

 

 

连着前面(后面)的房间只能有一个。

 

 

代码思路都给你们了。祝早日AC。

希望你们可以学点东西。

 

 

这题一般用线段树加区间合并:

我觉得线段树,我会头晕。我就想想别的办法了。

给个线段树链接。

链接

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值