POJ- 1083-Moving Tables-贪心

http://poj.org/problem?id=1083

参见 白书选择不相交区间问题 

选择不相交区间问题 中,要选尽可能多的区间覆盖整段, 是根据右端点从小到大排序,这样能得到的是局部最优解,由于只需要做一次,所以此处局部最优解也是全局最优解。

而对于本题,选择的过程是多次的,因此按照上面的贪心法则 会出现  下面的情况:

在当前的局部贪心过程中,【1,5】、【2,4】都是可以选的, 按照 【选择不相交区间问题 】会选【2,4】这个区间, 而这样  会导致 【1,1】这段空间浪费了,那么在下一次的局部贪心中  ,只能选【1,5】了,如果此时前面的区间需要用到 【1,1】这部分,却发现被 【1,5】占用了,那么就不能同时选上了。。就无法达到全局最优。

如果我们按照 左端点从小到大排序,那么我们就可以避免  【区间左边部分被浪费掉】的情况, 而右边部分的先后,是不影响答案的。



-------还有个方案,直接数出  被覆盖过次数最多的点,就是答案了。。。。


#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <iostream>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>  
using namespace std;  
const int inf=2147483647;

int min(int a,int b){return a<b?a:b;}
int min(int a,int b,int c){return min(min(a,b),c);}

struct node
{
	int x,y; 
};
node tm[205]; 
bool cmp(node a,node b)
{
 
	return a.x<b.x;
}

 
int main()
{ 
	int t;cin>>t;
	int n;
	int i;
	int x,y;
	while(t--) 
	{
		scanf("%d",&n);
		for (i=1;i<=n;i++)
		{
			scanf("%d%d",&x,&y);
			if (y%2) y++;
			if (x%2) x++; 
			x/=2;
			y/=2;
			if (x>y)
				swap(x,y); 
			tm[i].y=y;
			tm[i].x=x;  
		}
	
		sort(tm+1,tm+1+n,cmp); 
		int cun=0; 
		int used[205];
		int j;
	
		int ans=0;
		memset(used,0,sizeof(used));
	 int tmp_n=n;
		while(cun<n)
		{ 
		
			int ok=0; 
			for (i=1;i<=tmp_n;i++)
			{
				if (used[i]==0)
					tm[++ok]=tm[i];
			}
			tmp_n=ok;
		 	memset(used,0,sizeof(used));
			ans++; 
			int last=0;
			for (i=1;i<=ok;i++)
			{
				node tmp=tm[i];
				if (tmp.x<=last) continue; 
				last=tmp.y;
				used[i]=1;
				cun++; 
			} 
			
		}
		printf("%d\n",ans*10);
		
		
	}
	return 0;  
}


你可能感兴趣的:(POJ- 1083-Moving Tables-贪心)