三分查找Gym - 101246J

枚举间距会发现,如果间距过大或过小都会让答案太大。所以可以得出答案关于点间距的函数应该是个凹函数。

三分算法技能加点

一开始怎么跑都超时, 后来强制跑了300次WA23     700次就过了。

××这次学会了强制让二分和三分缩小查找次数。

××范围 和强制对的次数都比较重要。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int N=505;
const double eps = 1e-15;
double p[N];
int n;
int chan;
double mbs(double a){
    return a>=0?a:-a;
}
double check(double X){
        double ans = inf;
        for(int i=1;i<=n;i++){
            double tpans = 0;
            for(int j=1;j<i;j++){
                tpans += mbs(p[i] - (i - j)*X - p[j]);
            }
            for(int j=i+1;j<=n;j++){
                tpans +=  mbs(p[i] + (j - i)*X - p[j] ) ;
            }
            if(tpans < ans){
                ans = tpans;
                chan = i;
            }
        }
        return ans;
}

int main() {
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt","w", stdout);
    scanf("%d", &n);
    for(int i=1;i<=n;i++){
        scanf("%lf",&p[i]);
    }
    double l = 0, r = 1000000.0;
    int cnt = 700;
    while(eps<mbs(r - l) && cnt--){
        double mid = (l+r)/2;
        double midd = (mid + r)/2;
        if(check(mid) > check(midd)+eps){
            l = mid;
        }
        else r = midd;
    }
    l = check(l)>check(r)?r:l;
    double ans = check(l);
    printf("%.4f\n", ans);
    for(int i=1;i<chan;i++){
        printf("%.10f ", p[chan] -(chan-i)*l);
    }
    printf("%.10f ", p[chan]);
    for(int i=chan+1;i<=n;i++){
        printf("%.10f ",p[chan]+(i-chan)*l);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/khn64/article/details/80023066
今日推荐