题目地址:UVa 11134
这题因为行与列是无关的,互无影响的。所以可以将行或列分开来计算。这就相当于转化成了在期间[1,n]内选择n个不同的整数,使得第i个整数在闭区间[Li,Ri]内。这就转换成了一个贪心问题了。但是注意不能先按照左端点排序,再按右端点排序,然后尽量往左边放,比如,(1,1),(1,3),(2,2),这样是不对的,应该按右端点为主关键字排序,再按左端点为次关键字排序。看到网上的方法全都是用每次选一个数后,都要在后面的区间中删去这个数,还要用到优先队列。。感觉没必要这样做。。只要把排序关键字换换就可以了。
代码如下:
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <map> #include <set> #include <algorithm> using namespace std; int a[6000], b[6000], _hash[6000]; struct node { int l, r, num; }x[100000], y[100000]; int cmp(node x, node y) { if(x.r==y.r) return x.l<y.l; return x.r<y.r; } int main() { int n, i, j, flag, z; while(scanf("%d",&n)!=EOF&&n) { for(i=0;i<n;i++) { scanf("%d%d%d%d",&x[i].l,&y[i].l,&x[i].r,&y[i].r); x[i].num=i; y[i].num=i; } memset(_hash,0,sizeof(_hash)); sort(x,x+n,cmp); sort(y,y+n,cmp); z=0; for(i=0;i<n;i++) { flag=0; for(j=x[i].l;j<=x[i].r;j++) { if(!_hash[j]) { a[x[i].num]=j; _hash[j]=1; flag=1; break; } } if(!flag) { z=1; break; } } if(z) { printf("IMPOSSIBLE\n"); continue ; } memset(_hash,0,sizeof(_hash)); z=0; for(i=0;i<n;i++) { flag=0; for(j=y[i].l;j<=y[i].r;j++) { if(!_hash[j]) { b[y[i].num]=j; _hash[j]=1; flag=1; break; } } if(!flag) { z=1; break; } } if(z) { printf("IMPOSSIBLE\n"); continue ; } for(i=0;i<n;i++) { printf("%d %d\n",a[i],b[i]); } } return 0; }
(白书训练计划)UVa 11134 Fabled Rooks(贪心)
原文地址:http://blog.csdn.net/scf0920/article/details/39077457