UVA 11134 Fabled Rook 枚举 multiset加速

来源:互联网 发布:up to date数据库官网 编辑:程序博客网 时间:2024/06/05 07:02

        题意说的是给出一个长度为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;}


原创粉丝点击