UVA 11134 Fabled Rook 枚举 multiset加速

        题意说的是给出一个长度为n的国际象棋的棋盘,然后给出n个车的可以放置的范围,范围是一个矩形,用左上和右下两对数来描述,问是否存在方式使得每个车都放在他自己的范围里面且相互不冲突

        这里x方向和y方向是不相关的,x方向和y方向不相关的意思就是,假若当前的车放在(x0,y0)处会导致x轴方向上的冲突,那么,无论y怎么变化,冲突依然是存在的

        同理,这里的y方向和x方向也是不相关的,道理同上

        也就是说,x方向的安排和y方向的安排是两个独立的存在

        那么问题就变成了,选出n个互不相同的整数,使得第i个整数落在区间[xi1,xi2]范围内。

        做法是贪心,枚举当前的列数col,由于题目的意思是每一列都要放置一个,因此只要有一次不成功的放置,即是impossible。考虑用当前的列数去匹配一个区间,当然是匹配能匹配的,且区间的右界最靠近col 的区间来匹配。

        具体实现的时候用了一个multiset来储存区间以及这个区间是第几个输入的,multiset里按照区间的右界为小优先,右界相等左界小的优先来排序,因此能够保证在扫描区间的时候,第一个能够匹配的区间就是右界最靠近col的区间

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>

using namespace std;
const int maxm=5010;
typedef pair<int,int> pa;

struct Node{
    int x,y,ord;
    explicit Node(int a=0,int b=0,int c=0):x(a),y(b),ord(c){};
    bool operator<(const Node& a)const{return x<a.x||x==a.x&&y<a.y;}
};
multiset<Node> s[2];
int n,arr[maxm][2];
bool judge(int ind);

int main(){
    ios_base::sync_with_stdio(0);
    while(cin>>n&&n){
        for(int i=0,x1,x2,y1,y2;i<n;++i){
            cin>>x1>>y1>>x2>>y2;
            s[0].insert(Node(x2,x1,i));
            s[1].insert(Node(y2,y1,i));
        }
        if(judge(0)&&judge(1))
        for(int i=0;i<n;++i)
            cout<<arr[i][0]<<' '<<arr[i][1]<<endl;
        else
            cout<<"IMPOSSIBLE\n";
        s[0].clear();s[1].clear();
    }
    return 0;
}

bool judge(int ind){
    for(int col=1,flag=1;s[ind].size()&&col<=n;++col,flag=1){
        for(auto it=s[ind].begin();it!=s[ind].end();++it)
        if(it->y<=col&&it->x>=col){
            arr[it->ord][ind]=col,flag=0;
            s[ind].erase(it);
            break;
        }
        if(flag)
            return false;
    }
    return true;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值