UVA 12307 旋转卡壳

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=24011

给定n个点3~1e5,求出包含所有点的面积最小的矩形,周长最小矩形,输出最小面积和最小周长

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include <algorithm>
using namespace std;

#define For(i,a,b) for(int (i)=(a);(i) < (b);(i)++)
#define rof(i,a,b) for(int (i)=(a);(i) > (b);(i)--)
#define IOS ios::sync_with_stdio(false)
#define lson l,m,rt <<1
#define rson m+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a))

typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-11;
const double INF = 1e8;
const double PI = acos(-1.0);
const double TWO_PI = PI * 2;
template <class T> T sqr(T x) { return x * x;}

struct Point
{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y){}
};
typedef Point Vector;


//点-点=向量
Vector operator - (Point A, Point B) { return Vector(A.x-B.x,A.y-B.y);}
Vector operator *(Vector A, double p){return Vector(A.x*p,A.y*p); }
Vector operator /(Vector A, double p){return Vector(A.x/p,A.y/p); }
Vector operator +(Vector A, Vector B){ return Vector(A.x+B.x,A.y+B.y);}

//三态比较函数
int dcmp(double x){
    if(fabs(x)<eps) return 0;
    else return x<0?-1:1;
}
double Dot(Vector A, Vector B) { return A.x*B.x+A.y*B.y; }
double Cross (Vector A,Vector B){ return A.x*B.y-A.y*B.x; }
double Length(Vector A) {return sqrt(Dot(A,A)); }
double Dist(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
double Dist2(Point A, Point B){ return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y); }
double Angle(Vector A, Vector B){ return acos(Dot(A,B)/Length(A)/Length(B));}//返回A,B夹角[0,PI]
bool operator < (const Point &a,const Point &b) {return a.x<b.x||(a.x==b.x&&a.y<b.y); }
bool operator ==  (const Point &a,const Point &b){return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0; }
Vector Normal(const Vector& A) { double L = Length(A); return Vector(-A.y/L, A.x/L); }//左转90°

// 点集凸包
// 如果不希望在凸包的边上有输入点,把两个 <= 改成 <
// 如果不介意点集被修改,可以改成传递引用
vector<Point> ConvexHull(vector<Point> p)
{
    sort(p.begin(), p.end());
    p.erase(unique(p.begin(), p.end()), p.end());
    int n=p.size();
    int m=0;
    vector<Point> ch(n+1);
    for(int i=0;i<n;i++){
        while(m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
        ch[m++]=p[i];
    }
    int k=m;
    for(int i=n-2;i>=0;i--){
        while(m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
        ch[m++]=p[i];
    }
    if(n>1) m--;
    ch.resize(m);
    return ch;
}
//
void Qiake(vector<Point> & p,double & area,double & len){
	vector<Point> ch=ConvexHull(p);
	int n=ch.size();
	ch.push_back(ch[0]);
	int v=1,l=1,r=1;
	area=1e15,len=1e15;
	for(int u=0;u<n;u++){
		while(Cross(ch[u+1]-ch[u],ch[v+1]-ch[v])>eps) v=(v+1)%n;
		while(Dot(ch[u+1]-ch[u],ch[r+1]-ch[r])>eps) r=(r+1)%n;
		if(u==0) l=(r+1)%n;
		while(Dot(ch[u+1]-ch[u],ch[l+1]-ch[l])<-eps) l=(l+1)%n;
		//u,v相对,l,r相对  u,r,v,l
		double d=Dist(ch[u+1],ch[u]);
		double h=Cross(ch[u+1]-ch[u],ch[v]-ch[u])/d;//u到当前边的距离
		double w=(Dot(ch[r]-ch[u],ch[u+1]-ch[u])-Dot(ch[l]-ch[u],ch[u+1]-ch[u]))/d;
		area=min(area,h*w);
		len=min(len,2*(h+w));
	}
}

int n;
vector<Point> p;
int main()
{

	while(scanf("%d",&n)){
		if(n==0) break;
		p.clear();
		for(int i=0;i<n;i++){
			double x,y;
			scanf("%lf%lf",&x,&y);
			p.push_back(Point(x,y));
		}
		double ans1,ans2;
		Qiake(p,ans1,ans2);
		printf("%.2f %.2f\n",ans1,ans2 );
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值