您的位置:首页 > 其它

UVALive - 4356 Fire-Control System 三角函数+暴力+剪枝

2015-03-01 14:46 387 查看
题目大意:平面上有n个点,你的任务是以(0,0)为圆心画一个扇形,至少覆盖其中的k个点,使得该扇形的面积最小

解题思路:先把每个点和圆心的距离计算出来,然后再一次排序,统计出以此距离为半径的圆里面有多少个点(第一次剪枝)

如果该半径已经被计算过了就不用再计算了(第二次剪枝)

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;
#define maxn 5010
#define INF 0x3f3f3f3f
const double pi = acos(-1.0);
int n, k;
struct Point{
	int x, y, cnt;
	double r, c;
	void count() {
		r = sqrt(x * x * 1.0 + y * y * 1.0);
		c = atan2(y,x);
		cnt = 1;
	}
}p[maxn], que[maxn];

int cmpR(const Point a, const Point b) {
	return a.r < b.r;
}

int cmpC(const Point a, const Point b) {
	return a.c < b.c;
}

double solve() {
	if(k == 0)
		return 0;
	double ans = INF;
	set<double> s;
	sort(p,p+n,cmpC);
	for(int i = 0; i < n; i++) {
		if(p[i].cnt < k)
			continue;
		double R = p[i].r, C = 2 * pi;	
		if(s.find(R) != s.end())
			continue;
		s.insert(R);
		int tmp = 0;
		for(int j = 0; j < n; j++)
			if(p[j].r < R || fabs(p[j].r - R) < 1e-9) {
				que[tmp++] = p[j];
				if(tmp >= k)
					C = min(C,que[tmp-1].c-que[tmp-k].c);
			}
		if(tmp < k)
			continue;
		for(int j = 0; j < k - 1; j++)
			C = min(C,que[j].c - que[tmp+j-k+1].c + 2 * pi);	

		ans = min(ans,R * R * C / 2);
	}
	return ans;
}

int main(){
	int mark = 1;
	while(scanf("%d%d",&n, &k) == 2 && n + k) {
		for(int i = 0; i < n; i++) {
			scanf("%d%d",&p[i].x, &p[i].y);
			p[i].count();		
		}
		sort(p,p+n,cmpR);	
		for(int i = 1; i < n; i++)
			p[i].cnt += p[i-1].cnt;
		printf("Case #%d: %.2lf\n",mark++, solve());
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: