UVa 11134 - Fabled Rooks

时间限制:3.000秒

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=2075


  要求在n × n的棋盘放n个车(1 ≤ n ≤ 5000),使得它们相互之间不会相互攻击,限制条件是第i个车只能放在矩形R[i]的范围之内,用xl[i],yl[i],xr[i],yr[i]四个整数表示矩形的左上角横坐标,左上角纵坐标,右下角横坐标,右下角纵坐标。按顺序输出n个车的位置,如果无解,输出“IMPOSSIBLE”。

  车之间不相互攻击就意味着这些车两两之间不再同一行、同一列上,所以行和列可以分开来算。

  把每个车的横坐标的范围存在数组中,然后按照先起点后终点的优先顺序从小到大排序,每次选择排第一的车,如果这辆车横坐标范围的起点超出了之前最后一个放置的车位置的横坐标+1,又或者这辆车的横坐标范围的终点小于之前最后一个放置的车的横坐标,那么无解。否则这辆车的横坐标就等于上一辆车横坐标+1。之后将所有车横坐标范围起点小于这辆车放置位置横坐标的都改成放置位置横坐标+1,然后在排序。

  纵坐标的计算与之类似。

  每次选择了一辆车之后要修改起点重新排序,如果直接sort的话效率太低,这个时候就可以使用优先队列,要修改起点的出队修改再入队。


#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       

using namespace std;

struct range {
    int a, b, n;
};

int n, x01, y01, x02, y02, pos;
range x[5010], y[5010];

class cmp_x {
public:
    bool operator () (const int &a, const int &b) const {
        if(x[a].a != x[b].a) return x[a].a > x[b].a;
        if(x[a].b != x[b].b) return x[a].b > x[b].b;
        return x[a].n > x[b].n;
    }
};
class cmp_y {
public:
    bool operator () (const int &a, const int &b) const {
        if(y[a].a != y[b].a) return y[a].a > y[b].a;
        if(y[a].b != y[b].b) return y[a].b > y[b].b;
        return y[a].n > y[b].n;
    }
};
class cmp_ans_x {
public:
    bool operator () (const int &a, const int &b) const { return x[a].n > x[b].n; }
};
class cmp_ans_y {
public:
    bool operator () (const int &a, const int &b) const { return y[a].n > y[b].n; }
};

priority_queue
       
       
         , cmp_x> que_x; priority_queue 
        
          , cmp_y> que_y; priority_queue 
         
           , cmp_ans_x> ans_x; priority_queue 
          
            , cmp_ans_y> ans_y; inline void init() { while(!que_x.empty()) que_x.pop(); while(!que_y.empty()) que_y.pop(); while(!ans_x.empty()) ans_x.pop(); while(!ans_y.empty()) ans_y.pop(); } bool solve() { pos = 0; while(!que_x.empty()) { int cur = que_x.top(); que_x.pop(); ++pos; if(x[cur].a > pos || pos > x[cur].b) return false; x[cur].a = x[cur].b = pos; ans_x.push(cur); while(!que_x.empty() && x[que_x.top()].a <= pos) { int t = que_x.top(); que_x.pop(); x[t].a = pos + 1; que_x.push(t); } } pos = 0; while(!que_y.empty()) { int cur = que_y.top(); que_y.pop(); ++pos; if(y[cur].a > pos || pos > y[cur].b) return false; y[cur].a = y[cur].b = pos; ans_y.push(cur); while(!que_y.empty() && y[que_y.top()].a <= pos) { int t = que_y.top(); que_y.pop(); y[t].a = pos + 1; que_y.push(t); } } return true; } int main() { ios::sync_with_stdio(false); while(cin >> n && n) { init(); for(int i = 0; i != n; ++i) { cin >> x01 >> y01 >> x02 >> y02; x[i].a = x01, x[i].b = x02, x[i].n = i; y[i].a = y01, y[i].b = y02, y[i].n = i; que_x.push(i), que_y.push(i); } if(!solve()) cout << "IMPOSSIBLE" << endl; else { while(!ans_x.empty() && !ans_y.empty()) { cout << x[ans_x.top()].a << ' ' << y[ans_y.top()].a << endl; ans_x.pop(), ans_y.pop(); } } } } 
           
          
         
       
      
      
     
     
    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值