[hdu5251]矩形面积 凸包+旋转卡壳 计算几何

Problem Description
小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些矩形包围起来的面积最小的矩形的面积是多少。
 

Input
第一行一个正整数 T,代表测试数据组数( 1T20),接下来 T 组测试数据。

每组测试数据占若干行,第一行一个正整数 N(1N<≤1000),代表矩形的数量。接下来 N 行,每行 8 个整数 x1,y1,x2,y2,x3,y3,x4,y4,代表矩形的四个点坐标,坐标绝对值不会超过10000。
 

Output
对于每组测试数据,输出两行:

第一行输出"Case #i:",i 代表第 i 组测试数据。
第二行包含1 个数字,代表面积最小的矩形的面积,结果保留到整数位。
 

Sample Input
 
  
2 2 5 10 5 8 3 10 3 8 8 8 8 6 7 8 7 6 1 0 0 2 2 2 0 0 2
 

Sample Output
 
  
Case #1: 17 Case #2: 4
 

Source

题解:

本题属于旋转卡壳的模板题,如果第一次接触可以看这篇博客




AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int Maxn=100005; 
struct node{
	double x,y;
}a[Maxn],ans[Maxn];
double ojbk[Maxn];
int n,sum,cnt;
bool cmp(node x,node y){
	if(x.y!=y.y)return x.y<y.y;
	return x.x<y.x;
}
node operator -(const node &x,const node &y){
	node c;
	c.x=x.x-y.x;c.y=x.y-y.y;
	return c;
}
inline double cro(node x,node y){
	return x.x*y.y-x.y*y.x;
}
inline double dot(node x,node y){
	return x.x*y.x+x.y*y.y;
}
inline double f(double x){
	return x*x;
}
inline double dis(node x,node y){
	return sqrt(f(x.x-y.x)+f(x.y-y.y));
}
void convex(){
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){
		while(sum>=2&&(cro((ans[sum]-ans[sum-1]),(a[i]-ans[sum-1]))<=0)){
			sum--;
		}
		ans[++sum]=a[i];
	}
	int lim=sum;
	for(int i=n;i>=1;i--){
		while(sum>=lim+1&&(cro((ans[sum]-ans[sum-1]),(a[i]-ans[sum-1]))<=0)){
			sum--;
		}
		ans[++sum]=a[i];
	}
	sum--;
}
double mn(double x,double y){
	return x<y?x:y;
}
inline int step(int x){
	x++;
	if(x==sum+1)x=1;
	return x;
}
inline double ab(double x){
	return x>0?x:0;
}
void work(){
	double ansn=1e10,now;
	scanf("%d",&n);
	n*=4;
	int high=3,left,right=3;
	double di,lft,hht,rht,S,d;
	for(int i=1;i<=n;i++){
		scanf("%lf%lf",&a[i].x,&a[i].y);
	}
	sum=0;
	convex();
	ans[sum+1]=ans[1];
	for(int i=1;i<=sum;i++){
		while(cro((ans[i+1]-ans[i]),(ans[high]-ans[i]))<cro((ans[i+1]-ans[i]),(ans[step(high)]-ans[i])))
		high=step(high);
		while(dot((ans[i+1]-ans[i]),(ans[right]-ans[i]))<dot((ans[i+1]-ans[i]),(ans[step(right)]-ans[i])))
		right=step(right);
		if(i==1)left=step(right); 
		while(dot((ans[i+1]-ans[i]),(ans[left]-ans[i]))>dot((ans[i+1]-ans[i]),(ans[step(left)]-ans[i])))
		left=step(left);
		di=dis(ans[i],ans[i+1]);
		lft=-dot((ans[i+1]-ans[i]),(ans[left]-ans[i]))/di;lft=ab(lft); 
		rht=dot((ans[i+1]-ans[i]),(ans[right]-ans[i]))/di-di;rht=ab(rht);
		hht=cro((ans[i+1]-ans[i]),(ans[high]-ans[i]))/di;
		d=lft+rht+di;
		ansn=mn(ansn,hht*d);
		ojbk[i]=hht*d;
	}
	long long tmp=ansn+0.5;
	printf("%lld\n",tmp);
}
int main(){
	int t;
	scanf("%d",&t);
	for(int i=1;i<=t;i++){
		printf("Case #%d:\n",i);
		work();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lvyanchang/article/details/80424791