poj 3301 Texas Trip 三分

求n个点的最小包围正方形。

对于其中的任意两个点构成一条边, 

包围这条边 的正方形的边长,分析易得, 随着这条边的旋转角度的变化是  下凸曲线 ( 先下降后上升 ) 。

然而 对于 n*(n-1) 条边的状态和, 对于 旋转角度 x  ,所有边的状态和 是 求max (分析易得)。

所以 n 的下凸曲线 的max 构成的曲线 还是下凸曲线。

因此对于所有的点 通过旋转 求的面积 满足三分。


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <cstring>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <assert.h>
#include <queue>
#define REP(i,n) for(int i=0;i<n;i++)
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define ALLL(x) x.begin(),x.end()
#define SORT(x) sort(ALLL(x))
#define CLEAR(x) memset(x,0,sizeof(x))
#define FILLL(x,c) memset(x,c,sizeof(x))
using namespace std;
const double eps = 1e-9;
#define LL long long 
#define pb push_back
const int maxn  = 110;
double x[maxn];
double y[maxn];
int n ;
double  get_ans(double aaa){
	  
	  double up,down;
	  double left,right;
      for(int i=1;i<= n;i++){
      	     double a = cos(aaa)*x[i] - sin(aaa)*y[i];
      	     double b = cos(aaa)*y[i] + sin(aaa)*x[i];
      	   //  cout << x[i] << "  "<< y[i] << "  "<< a << " "  << b<<endl; 
      	     if(i==1){
      	     	up = down = a;
      	     	left = right = b;
      	     }else{
      	     	 up = max(up,a);
      	     	 down = min(down,a);
      	     	 left= min(left ,b);
      	     	 right= max(right,b);
      	     }
       }
      double ret = max(right - left ,up - down);
   //   cout << ret << endl ;
      
      return ret*ret;
}

void solve(){
    double left = 0;
    double right = acos(-1)/2;
    int t = 300;
    double ans ;
    while(t--){
    	double k = (right - left)/3;
        double lmid = left +k;
        double rmid = left + 2* k;
        double lans = get_ans(lmid);
        double rans = get_ans(rmid);
        ans = min(lans,rans);
        if(get_ans(lmid)<get_ans(rmid)){
        	   right = rmid ; 
        }else{
        	 left = lmid;
        }
    }
 //   cout << ans <<endl ;
     printf("%.2f\n",ans);
}
int main(){
	int t;
	cin >>t ;
    while(~scanf("%d",&n),t--){
    	for(int i=1;i<=n;i++){
    		scanf("%lf%lf",&x[i],&y[i]);
    	}
    	//cout << get_ans(45);
    	solve();
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值