一开始用的搜索,并且以为斜线也不能冲突,这样TLE+WA了很多次发现题目理解错了。。。斜线不用考虑。所以直接在二维的棋盘上考虑怎么放不好弄,注意到x和y无关(因为两个车完全可以在同一条斜线上,这点和皇后问题不一样),那么就可以分别考虑两个一维的问题:这是一种区间选点问题,在每个区间里都只选一个点,最后这些点分别是1到n。
从1到n一个格一个格的选车放,每步选择的最优区间是:该区间以前没选过,包含这个格,而且右端点是所有没选过的区间里最小的,那么我选择这个区间就最大程度的防止了以后的格子没得选(因为右端点选的是最小的)。
代码看了github上的紫书答案.
/* ***********************************************
Author :fisty
Created Time :2014/12/19 22:54:24
File Name :uva11134.cpp
************************************************ */
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <stdlib.h>
#include <time.h>
using namespace std;
// solve 1-D problem: find c so that a[i] <= c[i] <= b[i] (0 <= i < n)
bool solve(int *a, int *b, int *c, int n) {
fill(c, c+n, -1);
for(int col = 1;col <= n; col++){
//从1到n开始填数
int rock = -1; int maxb = n+1;
for(int i = 0;i < n; i++){
//找符合范围的区间最右端点
if(c[i] < 0 && b[i] < maxb && a[i] <= col){
rock = i; maxb = b[i];
}
}
if(rock < 0 || col > maxb) return false; //如果有的点没有被覆盖的区间或者当前点超过了区间的右端点
c[rock] = col;
}
return true;
}
const int maxn = 5000 + 5;
int n, x1[maxn], y1[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], &y1[i], &x2[i], &y2[i]);
if(solve(x1, x2, x, n) && solve(y1, y2, y, n))
for (int i = 0; i < n; i++) printf("%d %d\n", x[i], y[i]);
else
printf("IMPOSSIBLE\n");
}
return 0;
}