题意:在一个n*n的棋盘上放n个车,让它们不互相攻击,并且第i辆车在给定的小矩形内。

析:说实话,一看这个题真是没思路,后来看了分析,原来这个列和行是没有任何关系的,我们可以分开看,

把它变成两个一维问题,也就是说,我们可以把行看成是1-n,然后把x1-x2看成小区间,这样的话,

是不是就感觉简单的了,还有好几坑,被坑的惨惨的。

首先对行排序,按照每个右端点排,然后扫一遍,去找左端点,找到就立马选上(贪心),并且是一定满足的,

如果找不到,就退出,说明没有解。同理列也是这样。

后来看了Rujia Liu的代码,那叫一个精简啊,连结构体都没用,真是大神啊。

我的代码如下:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
const int maxn = 5000 + 10;
struct node{
    int x1, x2, y1, y2;
    int x, y, id;
    bool usedx, usedy;
};
node a[maxn];

bool cmp1(const node &p, const node &q){  return p.x2 < q.x2; }

bool cmp2(const node &p, const node &q){  return p.y2 < q.y2; }

bool cmp3(const node &p, const node &q){  return p.id < q.id; }

int main(){
    int n;
    while(scanf("%d", &n) && n){
        for(int i = 0; i < n; ++i){
            scanf("%d %d %d %d", &a[i].x1, &a[i].y1, &a[i].x2, &a[i].y2);
            a[i].usedx = a[i].usedy = false;
            a[i].id = i;
        }

        sort(a, a+n, cmp1);
        bool ok;
        for(int i = 0; i < n; ++i){
            ok = false;
            for(int j = 0; j < n; ++j){
                if(!a[j].usedx && a[j].x1 <= i+1){
                    if(a[j].x2 <= i)   break;
                    a[j].x = i+1;
                    a[j].usedx = true;
                    ok = true;
                    break;
                }
            }
            if(!ok)  break;
        }
        if(!ok){  printf("IMPOSSIBLE\n");  continue;  }

//        puts("++++");
        sort(a, a+n, cmp2);
        for(int i = 0; i < n; ++i){
            ok = false;
            for(int j = 0; j < n; ++j){
                if(!a[j].usedy && a[j].y1 <= i+1){
                    if(a[j].y2 <= i)   break;
                    a[j].y = i+1;
                    a[j].usedy = true;
                    ok = true;
                    break;
                }
            }
            if(!ok)  break;
        }
        if(!ok){  printf("IMPOSSIBLE\n");  continue;  }

        sort(a, a+n, cmp3);
        for(int i = 0; i < n; ++i)
            printf("%d %d\n", a[i].x, a[i].y);
    }
    return 0;
}

 

下面是Rujai Liu的代码真是膜拜啊:

#include<cstdio>
#include<cstring>
#include <algorithm>
using namespace std;

bool solve(int *a, int *b, int *c, int n) {
  fill(c, c+n, -1);
  for(int col = 1; col <= n; col++) {
    int rook = -1, minb = n+1;
    for(int i = 0; i < n; i++)
      if(c[i] < 0 && b[i] < minb && col >= a[i]) { rook = i; minb = b[i]; }
    if(rook < 0 || col > minb) return false;
    c[rook] = col;
  }
  return true;
}

const int maxn = 5000 + 5;
int n, x1[maxn], yy1[maxn], x2[maxn], y2[maxn], x[maxn], y[maxn];

int main() {
  while(scanf("%d", &n) == 1 && n) {
    for (int i = 0; i < n; i++)
      scanf("%d%d%d%d", &x1[i], &yy1[i], &x2[i], &y2[i]);
    if(solve(x1, x2, x, n) && solve(yy1, y2, y, n))
      for (int i = 0; i < n; i++) printf("%d %d\n", x[i], y[i]);
    else
      printf("IMPOSSIBLE\n");
  }
  return 0;
}