zoukankan      html  css  js  c++  java
  • [三分法初探]

    [Uva Error Curves]一些二次函数取max的交集还是一个下凸函数。三分即可

    #include <bits/stdc++.h>
    #define maxn 10010
    using namespace std;
    
    int n, a[maxn], b[maxn], c[maxn];
    
    #define F(i, x) a[i] * x * x + b[i] * x + c[i]
    
    inline double cal(double x){
    	double ret = -1e12;
    	for(int i = 1; i <= n; i ++)
    	    ret = max(ret, F(i, x));
    	return ret;
    }
    
    inline void solve(){
    	double l = 0, r = 1000;
    	for(int i = 1; i <= 300; i ++){
    		double len = (r - l) / 3;
    		double m1 = l + len, m2 = r - len;
    		if(cal(m1) < cal(m2))r = m2;
    		else l = m1;
    	}
    	printf("%.4lf
    ", cal(l));
    }
    
    int main(){
        int test;
        scanf("%d", &test);
        while(test --){
    		scanf("%d", &n);
    		for(int i = 1; i <= n; i ++)
    		    scanf("%d%d%d", &a[i], &b[i], &c[i]);
    	    solve();
        }
    
    	return 0;
    }
    

    [Zoj Light Bulb]列出数学式子,是一个对勾函数(可以直接解),或者三分,注意影子到地上的判断,不过D-x≤H??

    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    double H, h, D, P, Q;
    
    inline double check(double x){
    	return -x + P / x + Q;
    }
    
    void solve(){
    	P = D * (h - H), Q = D + H;
    	double l = 1e-9, r = min(H, D);
    	for(int i = 1; i <= 1000; i ++){
    		double len = (r - l) / 3;
    		double m1 = l + len, m2 = r - len;
    		if(check(m1) > check(m2))r = m2;
    		else l = m1;
    	}
    	printf("%.3lf
    ", check(r));
    }
    
    int main(){
    	int test;
    	scanf("%d", &test);
    	while(test --){
    		scanf("%lf%lf%lf", &H, &h, &D);
    		solve();
    	}
    	return 0;
    }
    

    [HDU Line belt]三分再三分

    #include <bits/stdc++.h>
    
    using namespace std;
    
    struct Point{
    	double x, y;
    	inline void read(){scanf("%lf%lf", &x, &y);}
    }A, B, C, D;
    #define Sqr(x) (x)*(x)
    double Len(const Point& a, const Point& b){
    	return sqrt(Sqr(a.x-b.x) + Sqr(a.y-b.y));
    }
    int P, Q, R;
    double T(double a, double b){
    	Point X, Y;
    	X.x = a * (B.x - A.x) + A.x;
    	X.y = a * (B.y - A.y) + A.y;
    	Y.x = b * (C.x - D.x) + D.x;
    	Y.y = b * (C.y - D.y) + D.y;
    	return Len(A, X) / P + Len(D, Y) / Q + Len(X, Y) / R;
    }
    
    double check(double a){
    	double l = 0, r = 1;
    	while(r - l > 1e-6){
    		double len = (r - l) / 3.0;
    		double m1 = l + len, m2 = r - len;
    		if(T(a, m1) < T(a, m2))r = m2;
    		else l = m1;
    	}return T(a, r);
    }
    
    int main(){
    	int test;
    	scanf("%d", &test);
    	while(test --){
    		A.read(), B.read(), C.read(), D.read();
    		scanf("%d%d%d", &P, &Q, &R);
    		double l = 0, r = 1;
    		while(r - l > 1e-6){
    			double len = (r - l) / 3.0;
    			double m1 = l + len, m2 = r - len;
    			if(check(m1) < check(m2))r = m2;
    			else l = m1;
    		}
    		printf("%.2lf
    ", check(r));
    	}
    	return 0;
    }
    

    [POJ 3301]Texas Trip

    如果平行于坐标轴的正方形很好计算

    如何计算歪的正方形嘞??

    旋转角度嘛。一个关于旋转角度的下凸函数

    然后三分角度QAQ orz神

    #include <cmath>
    #include <algorithm>
    #include <cstdio>
    #define maxn 100
    using namespace std;
    
    
    int n;
    
    struct Point{
    	double x, y;
    }a[maxn], b[maxn];
    
    #define Sqr(x) x * x
    
    double check(){
    	double lf = 1e12, rg = -1e12;
    	double up = rg, dw = lf;
    	for(int i = 1; i <= n; i ++){
    		lf = min(lf, a[i].x);
    		rg = max(rg, a[i].x);
    		up = max(up, a[i].y);
    		dw = min(dw, a[i].y);
    	}
    	return Sqr(max(rg - lf, up - dw));
    }
    
    const double pi = acos(-1.0);
    
    double Mdf(double x){
    	for(int i = 1; i <= n; i ++){
    		a[i].x = b[i].x * cos(x) - b[i].y * sin(x);
    		a[i].y = b[i].x * sin(x) + b[i].y * cos(x);
    	}
    	return check();
    }
    
    void solve(){
    	double l = 0, r = pi;
    	for(int i = 1; i <= 10000; i ++){
    		double len = (r - l) / 3;
    		double m1 = l + len, m2 = r - len;
    		if(Mdf(m1) < Mdf(m2)) r = m2;
    		else l = m1;
    	}
    	printf("%.2lf
    ", Mdf(l));
    }
    
    int main(){
    	int test;
    	scanf("%d", &test);
    	
    	while(test --){
    		scanf("%d", &n);
    		for(int i = 1; i <= n; i ++)
    		    scanf("%lf%lf", &b[i].x, &b[i].y);
    		solve();
    	}
    
    	return 0;
    }
    

    [Codeforces 605C]

    首先这是一个线性规划问题,有100000个变元,2个约束条件。0并不是一个初始解,所以对偶一下,100000个约束条件,2个变元。发现并不能线性规划单纯形,考虑一些半平面的交是上凸函数,所以确定y1可以找出y2的值,所以可以三分啦(然而标解是二分+凸包)

    #include <bits/stdc++.h>
    #define maxn 100010
    using namespace std;
    
    int n, p, q;
    
    int a[maxn], b[maxn];
    
    double check(double y){
    	double ret = 0x7fffffff;
    	for(int i = 1; i <= n; i ++)
    		ret = min(ret, (1.0 - a[i] * y) / b[i]);
    	return q * ret + p * y;
    }
    
    int main(){
    	scanf("%d%d%d", &n, &p, &q);
    	int x = 0;
    	for(int i = 1; i <= n; i ++){
            scanf("%d%d", &a[i], &b[i]);
            if(a[i] > x) x = a[i];
    	}
    	double l = 0, r = 1.0 / x;
    	for(int i = 1; i <= 300; i ++){
    		double len = (r - l) / 3;
    		double m1 = l + len, m2 = r - len;
    		if(check(m1) < check(m2)) l = m1;
    		else r = m2;
    	}
    	printf("%.12lf
    ", check(l));
    	return 0;
    }
    

    [SDOI 2013]保护出题人

    #include <bits/stdc++.h>
    #define maxn 100010
    using namespace std;
    
    typedef long long ll;
    
    ll n, d;
    
    ll a[maxn], x[maxn];
    
    /*
    每一关的独立性。
    攻击力 = Max((sum[i] - sum[j-1]) / (xi + (i - j) * d))
    */
    
    ll sum[maxn];
    
    struct Point{
    	ll x, y;
    	Point(ll a = 0, ll b = 0):x(a), y(b){}
    };
    
    double operator * (const Point& a, const Point& b){
    	return (double)a.x * b.y - (double)a.y * b.x;
    }
    
    Point st[maxn];
    
    Point operator - (const Point &a, const Point &b){
    	return Point(a.x - b.x, a.y - b.y);
    }
    
    int top;
    
    int i;
    
    double check(int p){
    	return (double)(sum[i] - st[p].y) / (x[i] + i * d - st[p].x) ;
    }
    
    int main(){
    	scanf("%lld%lld", &n, &d);
    	for(int j = 1; j <= n; j ++)
    		scanf("%lld%lld", &a[j], &x[j]);
    	double ans = 0;
    	for(i = 1; i <= n; i ++){
    		sum[i] = sum[i-1] + a[i];
    		
    		Point now = Point(i * d, sum[i-1]);
    		while(top > 1 && (st[top] - st[top-1]) * (now - st[top]) <= 0)
    			top --;
    		st[++ top] = now;
    		int l = 1, r = top;
    		
    		while(r - l >= 3){
    			int m1 = (l + l + r) / 3, m2 = (l + r + r) / 3;
    			if(check(m1) < check(m2)) l = m1;
    			else r = m2;
    		}
    		int mx = l;
    		for(int j = l + 1; j <= r; j ++)
    			if(check(j) > check(mx))
    			    mx = j;
    		l = mx;
    		
    		ans += (double)(sum[i] - st[l].y) / (x[i] + i * d - st[l].x);
      	}
    
    	printf("%.0lf
    ", ans);
    	return 0;
    }
    
    /*
    Input
    5 2
    3 3
    1 1
    10 8
    4 8
    2 3
    Output
    7
    
     1≤n≤10^5,1≤d≤10^12,1≤x≤10^12,1≤a≤10^12
    */
    

      

    给时光以生命,而不是给生命以时光。
  • 相关阅读:
    getAttribute()方法
    getElementsByTagName()方法
    DOM方法 getElementsByName()方法
    python 与
    run_debug和run_demo的区别
    sh脚本写法
    使用snapshot继续训练网络
    安卓获取数据demo出现的问题
    查看文件大小
    重命名文件夹名字
  • 原文地址:https://www.cnblogs.com/Candyouth/p/5342863.html
Copyright © 2011-2022 走看看