UVA 11134 Fabled Rooks(贪心法,区间与选点问题)

x轴,y轴不相关,所以分开考虑

贪心法 可以这样思考,不同于定区间选点,而是定点选区间,所以理所当然,要选占用1~col最多位置的区间(因为该地方已经放置好),且尽可能保留占用col+1~n的位置区间为以后考虑;

那么我们要从col=1~n放,对于每个col选取[a,b]中 1) a最小 2)a相同时b最小的区间; 每选中一个区间就把他抹掉;

为什么那么选的原因:

1) a最小 : 因为col是从1到n选的 每次当然要利用a最小的区间,反正<col的位置的root都放好了,越晚选越吃亏

2)a相同时b最小的区间 :让col+1~n的空位越多越好,先把短的区间用掉喽别浪费资源;

代码如下:

#include<iostream>
#include<vector>
#include<queue>
#include<numeric>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<ctime>
using namespace std;
const int maxn=5000+5;
int n,x1[maxn],x2[maxn],y1[maxn],y2[maxn],x[maxn],y[maxn];

bool solve(int* a,int *b,int* c)   //[a,b] 
{
	memset(c,-1,sizeof(int)*n);  //  a[i] <= col <= b[i]
	/*fill(c,c+n,-1)  是对每一个int大小内存块初始化,而memset是对每个字节*/ 
	for(int col=1;col<=n;col++)  //在1~n给每个区间放个root 
	{
		int root=-1,minb=n+1;
		for(int i=0;i<n;i++)
			if(c[i]<0&&a[i]<=col&& b[i]<minb) root=i,minb=b[i];
		  //if(第i个区间未放过&&在左区间a小于要放的位置col&&还有更小的b) 
		if(root<0||minb<col) return false;
	  //if(放不了了||col为要放的位置>b即col在区间[a,b]外) 
		c[root]=col;
	}
	return true;
}

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)&&solve(y1,y2,y))
		for(int i=0;i<n;i++) printf("%d %d\n",x[i],y[i]);
		else printf("IMPOSSIBLE\n");
	}
}



你可能感兴趣的:(UVA 11134 Fabled Rooks(贪心法,区间与选点问题))