【Jason's_ACM_解题报告】Fabled Rooks

来源:互联网 发布:法院拍卖房产淘宝网址 编辑:程序博客网 时间:2024/05/18 01:43

Fabled Rooks

We would like to place n rooks, 1 <= n <= 5000, on a n×n board subject to the following restrictions
·The i-th rook can only be placed within the rectangle given by its left-upper corner (xli, yli) and its right-lower corner (xri, yri), where 1 <= i <= n, 1 <= xli <= xri <= n, 1 <= yli <= yri <= n.
·No two rooks can attack each other, that is no two rooks can occupy the same column or the same row.

Input
The input consists of several test cases. The first line of each of them contains one integer number, n, the side of the board. n lines follow giving the rectangles where the rooks can be placed as described above. The i-th line among them gives xli, yli, xri, and yri. The input file is terminated with the integer `0' on a line by itself.

Output
Your task is to find such a placing of rooks that the above conditions are satisfied and then output n lines each giving the position of a rook in order in which their rectangles appeared in the input. If there are multiple solutions, any one will do. Output IMPOSSIBLE if there is no such placing of the rooks.

Sample input
8
1 1 2 2
5 7 8 8
2 2 5 5
2 2 5 5
6 3 8 6
6 3 8 5
6 3 8 8
3 6 7 8
8
1 1 2 2
5 7 8 8
2 2 5 5
2 2 5 5
6 3 8 6
6 3 8 5
6 3 8 8
3 6 7 8
0


Sample Output
1 1
5 8
2 4
4 2
7 3
8 5
6 6
3 7
1 1
5 8
2 4
4 2
7 3
8 5
6 6
3 7

这道题想了很久,最后没办法就看了一下Liu的源码。

将二维的问题拆开来看作两个一维的是没问题的,因为每个Rook的区域范围的横纵坐标之前没有任何联系。

一开始我简单的认为将所有区间段记录原始顺序然后排序,并依次由1至N赋值,如果遇到当前赋值没有在当前区间范围内则输出IMPOSSIBLE。但是我忽略了区间相互包含的问题了。

正确的思路应该是关注棋盘,而非每个棋子的合法区域。对于棋盘的每一行或者每一列,查找所有棋子满足上界小于当前行或列,下界又最小的。若扫描的某一行或列时,没有任何一个棋子的上界小于该行或列(即check函数的plc==-1判断条件),或是没有任何一个棋子的下界大于该行或列(即check函数的line>minR判断条件),则输出IMPOSSIBLE。

所以以后但凡遇到与区间有关的问题,一定要考虑区间包含的情况。当题目难易解决的时候不要只注意区间,可以换一个角度考虑。


另外,memset函数在<cstring>头文件下、fill函数在<algorithm>头文件下。具体的区别可以看check函数的注释部分,亲自跑一下就明白了,这一点很致命。


附代码如下:
#include<cstdio> #include<cstring>#include<algorithm>using namespace std;#define MAXN (5000+5)struct ROOK{int L,R;};int n,x[MAXN],y[MAXN];bool impossible;ROOK row[MAXN],col[MAXN];void check(ROOK* rooks,int* dd){fill(dd,dd+n,-1);//memset(dd,-1,sizeof(dd));//for(int i=0;i<n;i++)printf("%d ",dd[i]);printf("\n");for(int line=1;line<=n;line++){int plc=-1,minR=n+1;for(int i=0;i<n;i++){if(dd[i]==-1&&line>=rooks[i].L&&rooks[i].R<minR){plc=i;minR=rooks[i].R;}}if(plc==-1||line>minR){impossible=true;return;}dd[plc]=line;}}int main(){//freopen("in.txt","r",stdin);while(scanf("%d",&n)==1&&n){for(int i=0;i<n;i++){int x1,x2,y1,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);row[i]=(ROOK){x1,x2};col[i]=(ROOK){y1,y2};}impossible=false;check(row,x);check(col,y);if(impossible){printf("IMPOSSIBLE\n");}else{for(int i=0;i<n;i++){printf("%d %d\n",x[i],y[i]);}}}//fclose(stdin);return 0;}

0 0
原创粉丝点击