UVA 10173

bitch bitch bitch...

TLE,WA一大坨,我是在拿生命来JUDGE啊。。

不得不说,UVA上的数据根本不是随机的,而是有预谋的。

for(int i=2;i<n;i++){
  while(stop>1&&cross(p[i],p[st[stop-1]],p[st[stop-2]])>=0) stop--;   //这个我本来是cross(p[i],p[st[stop-1]],p[st[stop-2]])>0
  st[stop++]=i;
}

因为没加上一个“=”号,就把边上所有共线的点都搞上了,之后,由于N太大,无可奈何的TLE、WA了。呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵吕森哥哥哥哥哥可可

算法如下:

  1. 计算全部四个多边形的端点, 称之为 xminP, xmaxP, yminP, ymaxP。
  2. 通过四个点构造 的四条切线。 他们确定了两个卡壳集合。
  3. 如果一条(或两条)线与一条边重合, 那么计算由四条线决定的矩形的面积, 并且保存为当前最小值。 否则将当前最小值定义为无穷大。
  4. 顺时针旋转线直到其中一条和多边形的一条边重合。
  5. 计算新矩形的面积, 并且和当前最小值比较。 如果小于当前最小值则更新, 并保存确定最小值的矩形信息。 
  6. 重复步骤4和步骤5, 直到线旋转过的角度大于90度。
  7. 输出外接矩形的最小面积。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;

struct point
{
    double x,y;
}p[1005];

int ans[1005],st[1005],stop,cnt,n;

int DB (double d){
	if (fabs(d)<1e-8)
		return 0;
	return d>0?1:-1;
}
double cross (point a,point b,point c){
	return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}
double dot(point a,point b,point c){
    return (a.x-c.x)*(b.x-c.x)+(a.y-c.y)*(b.y-c.y);
}
bool cmp(point A,point B){
	if(A.y<B.y) return true;
	else if(A.y==B.y){
		if(A.x<B.x)return true;
	}
	return false;
}

void forTU(){
	stop=cnt=0;
	st[stop++]=0; st[stop++]=1;
	for(int i=2;i<n;i++){
		while(stop>1&&cross(p[i],p[st[stop-1]],p[st[stop-2]])>=0) stop--;
		st[stop++]=i;
	}
	for(int i=0;i<stop;i++)
	ans[cnt++]=st[i];
	stop=0; st[stop++]=n-1; st[stop++]=n-2;
	for(int i=n-3;i>=0;i--){
		while(stop>1&&cross(p[i],p[st[stop-1]],p[st[stop-2]])>=0) stop--;
		st[stop++]=i;
	}
	for(int i=1;i<stop;i++){
		ans[cnt++]=st[i];
	}
}

double roating(){
	cnt--;
    if(n<3) return 0;
    int i,m=1,q=1,r;
    double anst=1e10,a,b,c;
    for(i=0;i<cnt;i++){
		while (DB(cross(p[ans[(i+1)]],p[ans[(m+1)]],p[ans[i]])-cross(p[ans[(i+1)]],p[ans[m]],p[ans[i]])) >0)
  		m=(m+1)%cnt;
        while (DB(dot(p[ans[(q+1)]],p[ans[(i+1)]],p[ans[i]])-dot(p[ans[q]],p[ans[(i+1)]],p[ans[i]])) >0)
        q=(q+1)%cnt;
        if (i==0)
		r=q;
        while(DB(dot(p[ans[(r+1)]],p[ans[(i+1)]],p[ans[i]])-dot(p[ans[r]],p[ans[(i+1)]],p[ans[i]])) <= 0)
        r=(r+1)%cnt;
        a=cross(p[ans[(i+1)]],p[ans[m]],p[ans[i]]);
        b=dot(p[ans[q]],p[ans[(i+1)]],p[ans[i]])-dot(p[ans[r]],p[ans[(i+1)]],p[ans[i]]);
        c=dot(p[ans[(i+1)]],p[ans[(i+1)]],p[ans[i]]);
        anst=min(anst,a*b/c);
    }
    return anst;
}

int main (){  
    while (scanf("%d",&n) && n!=0) {  
        for (int i=0;i<n;i++)
		scanf("%lf%lf",&p[i].x,&p[i].y);
		sort(p,p+n,cmp);   
        forTU();  
        printf("%.4lf\n",roating());  
    }  
    return 0;  
}

  

 

转载于:https://www.cnblogs.com/jie-dcai/p/3893278.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值