ACWing123(二维坐标离散化或双指针)

121. 赶牛入圈 - AcWing题库

做法1:双指针

AC代码

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 510;

pair<int,int> a[N];
int c, n;

bool check(int now)
{
	for(int i = 1; i <= n; i ++ )	//确定最大左右边界 i, j 
	{
		int j = 0;
		while(j <= n && a[j].first - a[i].first <= now)	j ++;
/*
在点集 [i,n] 里面查找以与左边界 i 距离小于 now 的点 
可以会问如果 j 在 i 的左侧怎么办,因为这里显然有j < i 的情况,但其实是不需要判断的
因为区间长度 j - i + 1是可以忽略掉在 i 左侧的 j 的情况
(1)到最后 j 都在 i 的左侧,那么j - i + 1 <= 0 恒成立,返回flase
(2)一部分 j 在 i 左侧,一部分 j 在 i 右侧,j - i + 1 不包含 j 在 i 左侧的 j 
可能会问直接在i里面加上 j > i 的判断不就好了?其实这样是不好的,因为不方便统计 j 的个数 
*/
		j --;	//因为 j = 0处 a[j] 没有定义,但 a[j] 又明显符合,所以 j--, 
		if(j - i + 1 < c)
			return false;
/*
这里合适的话不能返回true,因为这里只是确定了X轴的区间是满足的,还没有确定Y轴
即如果Y轴所需要的区间边长大于我们check的边长now,也是不符合的 	
但如果X轴的区间边长都不满足,一定不满足,直接返回false		
*/

		for(int k = i; k <= j; k ++ )	//检查Y轴,枚举每一个点的Y轴上下界 
		{
			int l = a[k].second, r = a[k].second + now, ans = 0;//以该点Y轴的范围作为上下边界	 
			for(int u = i; u <= j; u ++ )	//查找符合的点 
				if(a[u].second >= l && a[u].second <= r)
					ans++;
			if(ans >= c)
				return true;
		}
		
	}
	return false;
}

int main()
{
	cin >> c >> n;
	for(int i = 1; i <= n; i ++ )
	{
		int x, y;
		cin >> x >> y;
		a[i] = {x, y};	
	} 
	
	sort(a + 1, a + n + 1);		//不排序 check 函数毫无意义 
	//默认排序:first从到大排序,first相同时second从小到大排序 
	
	int l = 1, r = 10000; 
	while(l < r)
	{
		int mid = l + r >> 1;
		if(check(mid - 1))//因为每一个草占据一个矩形,所以求得的半径要大1,遍历的时候就要减1
			r = mid; 
		else	
			l = mid + 1;
	}
	
	cout << l << endl;
	
	return 0;
}

题解:AcWing 121. 赶牛入圈 - AcWing 

做法2:二维坐标离散化

posted @ 2022-05-05 08:42  光風霽月  阅读(21)  评论(0编辑  收藏  举报