POJ 3301——三分搜索

  • 题意:给定一些点,找出包含这些点的最小的正方形。
  • 分析:首先在标准坐标系中,确定一个边平行于坐标轴的正方形。然后旋转坐标轴,在(0,π/2)区间内旋转,每次确定的正方形面积是凹函数,找出其中面积最小的正方形即可。
    注意:坐标旋转公式
    在这里插入图片描述
  • 代码
#include "bits/stdc++.h"
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mk make_pair
typedef long long ll;
const int maxn = 1e3 + 7;
const int INF = 1e6;
const double EPS = 1e-12;           //三分的EPS要非常小
const double PI = acos(-1.0);           //PI的写法
int t,n;
int x[maxn],y[maxn];
double func(double t){
    
    
    double x1,y1;
    double minx, miny;
    double maxx, maxy;
    minx = miny = INF; maxx = maxy = -INF;
    for (int i = 0; i < n; i++) {
    
    
        x1 = x[i] * cos(t) - y[i] * sin(t);
        y1 = y[i] * cos(t) + x[i] * sin(t);
        minx = min(x1,minx);
        miny = min(y1,miny);
        maxx = max(x1,maxx);
        maxy = max(y1,maxy);
    }
    double l = max(maxx - minx,maxy - miny);
    return pow(l,2);
}
int main(){
    
    
    // freopen("1.txt","r",stdin);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>t;
    while (t--) {
    
    
        cin>>n;
        for (int i = 0; i < n; i++) {
    
    
            cin>>x[i]>>y[i];
        }
        double l = 0, r = PI/2;
        while (r - l > EPS) {
    
    
            double midl = l + (r - l)/3;
            double midr = r - (r - l)/3;
            if (func(midl) > func(midr)) {
    
    
                l = midl;
            }else r = midr;
        }
        printf("%.2lf\n",func(r));
    }
    return 0;
}

  • 遇到的问题:
    (1)首先是cin的问题,HDU 4355,虽然cin.tie 以及 sync_with_stdio,但依旧TLE,此题数据较小,所以不用scanf也可。
    (2)然后是EPS的问题,三分的EPS要小,此题开始我将EPS设置为1e-4,结果WA了,看了别人的题解发现都设置到1e-12。不过我明白了三分的EPS一定要小!
    (3)然后是PI的问题,每次我都设置为3.14,一直忘记可以设置为 acos(-1).此后要牢记。

猜你喜欢

转载自blog.csdn.net/qq_39763472/article/details/105083921