1. 程式人生 > >【三分法】【SCOI2010】傳送帶

【三分法】【SCOI2010】傳送帶

【題目描述】
在一個2維平面上有兩條傳送帶,每一條傳送帶可以看成是一條線段。兩條傳送帶分別為線段AB和線段CD。lxhgww在AB上的移動速度為P,在CD上的移動速度為Q,在平面上的移動速度R。現在lxhgww想從A點走到D點,他想知道最少需要走多長時間
【輸入】
輸入資料第一行是4個整數,表示A和B的座標,分別為Ax,Ay,Bx,By
第二行是4個整數,表示C和D的座標,分別為Cx,Cy,Dx,Dy
第三行是3個整數,分別是P,Q,R
【輸出】
輸出資料為一行,表示lxhgww從A點走到D點的最短時間,保留到小數點後2位
【樣例輸入】
0 0 0 100
100 0 100 100
2 2 1
【樣例輸出】
136.60
【資料範圍】
對於100%的資料,1<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000
1<=P,Q,R<=10
程式碼不算長,只是其中加了個Point類(可供座標的加減乘除運算),佔了一定篇幅。

此題考察三分法。

原問題可以抽象成以下問題:
線上段AB上找一點E,線上段CD上找一點F,使得AE / p + EF / r + FD / q最小。

不難看出,E,F點一定是唯一的。
也就是說,關於E,F的目標函式在定義域內一定只有一個極值點。
那麼可以直接三分E和F,求得最小值即可。

Accode:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>

const double MAX = 1e198;
const double MIN = -MAX;
const double zero = 1e-12;

template <typename _Tp>
class Point
{
private:
    _Tp _x, _y;
public:
    Point() {_x = _y = 0; }
    Point(_Tp x, _Tp y)
    {
        _x = x;
        _y = y;
    }
    _Tp x();
    _Tp y();
    Point &operator=(Point p)
    {
        _x = p.x();
        _y = p.y();
        return *this;
    }
    Point operator+(Point b) const
    {
        Point c(_x + b.x(), _y + b.y());
        return c;
    }
    Point operator-(Point b) const
    {
        Point c(_x - b.x(), _y - b.y());
        return c;
    }
    Point operator*(_Tp p)
    {
        Point c(_x * p, _y * p);
        return c;
    }
    Point operator/(_Tp p)
    {
        Point c(_x / p, _y / p);
        return c;
    }
    Point &operator+=(Point b)
    {
        _x += b.x();
        _y += b.y();
        return *this;
    }
    Point &operator-=(Point b)
    {
        _x -= b.x();
        _y -= b.y();
        return *this;
    }
    Point &operator*=(_Tp p)
    {
        _x *= p;
        _y *= p;
        return *this;
    }
    Point &operator/=(_Tp p)
    {
        _x /= p;
        _y /= p;
        return *this;
    }
};

int xA, xB, xC, xD, yA, yB, yC, yD;
Point <double> A, B, C, D;
double v1, v2, v3;

template <typename _Tp>
_Tp Point <_Tp> ::x()
{
    return _x;
}

template <typename _Tp>
_Tp Point <_Tp> ::y()
{
    return _y;
}

double sqr(double x)
{
    return x * x;
}

double dist(Point <double> a,
            Point <double> b)
{
    Point <double> tmp = b - a;
    return sqrt(sqr(tmp.x()) + sqr(tmp.y()));
}

double func(Point <double> E,
            Point <double> F)
{
    return dist(A, E) / v1
    + dist(E, F) / v3
    + dist(F, D) / v2;
}

double Find_F(Point <double> E)
{
    Point <double> L = C, R = D, tmp, p, q;
    double ans = MAX;
	//一切的列舉變數都應使用區域性變數。
    while (dist(L, R) > zero)
    {
        tmp = (R - L) / 3;
        p = L + tmp;
        q = R - tmp;
        double fp = func(E, p);
        double fq = func(E, q);
        if (fp > fq) L = p;
        else R = q;
        if (fp < ans) ans = fp;
        if (fq < ans) ans = fq;
	//更新ans的值。
    }
    if (dist(C, D) < zero) ans = func(E, C);
	//特殊處理,當C,D重合時,F取C。
    return ans;
}

double Find_E()
{
    Point <double> L = A, R = B, tmp, p, q;
    double ans = MAX;
	//一切的列舉變數都應使用區域性變數。
    while (dist(L, R) > zero)
    {
        tmp = (R - L) / 3;
        p = L + tmp;
        q = R - tmp;
        double fp = Find_F(p);
        double fq = Find_F(q);
        if (fp > fq) L = p;
        else R = q;
        if (fp < ans) ans = fp;
        if (fq < ans) ans = fq;
	//更新ans的值。
    }
    if (dist(A, B) < zero) ans = Find_F(A);
	//特殊處理:當A,B重合時,E取A。
    return ans;
}

int main()
{
	freopen("walk.in", "r", stdin);
	freopen("walk.out", "w", stdout);
    scanf("%d%d%d%d%d%d%d%d%lf%lf%lf",
          &xA, &yA, &xB, &yB, &xC, &yC,
          &xD, &yD, &v1, &v2, &v3);
    A = Point <double> (xA, yA);
    B = Point <double> (xB, yB);
    C = Point <double> (xC, yC);
    D = Point <double> (xD, yD);
    printf("%.2lf\n", Find_E());
	return 0;
}

相關推薦

SCOI2010傳送帶

【題目描述】 在一個2維平面上有兩條傳送帶,每一條傳送帶可以看成是一條線段。兩條傳送帶分別為線段AB和線段CD。lxhgww在AB上的移動速度為P,在CD上的移動速度為Q,在平面上的移動速度R。現在lxhgww想從A點走到D點,他想知道最少需要走多長時間 【輸入】 輸入資料

(洛谷3382 模板

printf log 含義 三分 tps ans 區間 bits int 如題,給出一個N次函數,保證在範圍[l,r]內存在一點x,使得[l,x]上單調增,[x,r]上單調減。試求出x的值。 輸入格式: 第一行一次包含一個正整數N和兩個實數l、r,含義如題目描述所示。

luogu 3382模板

include 表示 時空 return 三分 %d color upload printf 題目描述 如題,給出一個N次函數,保證在範圍[l,r]內存在一點x,使得[l,x]上單調增,[x,r]上單調減。試求出x的值。 輸入輸出格式 輸入格式: 第一行一次包含一個

[洛谷P3382]模板

esp ace print 註意 兩個 分法 ont define nbsp 題目大意:給出一個N次函數,保證在範圍[l,r]內存在一點x,使得[l,x]上單調增,[x,r]上單調減。試求出x的值。 解題思路:三分法。像我這種什麽函數都不知道的,只知道要三分。取兩個&ld

洛谷 P3382 模板

href con fine pla div cstring new toolbar lba P3382 【模板】三分法 題目描述 如題,給出一個N次函數,保證在範圍[l,r]內存在一點x,使得[l,x]上單調增,[x,r]上單調減。試求出

luogu3382模板

algorithm namespace sca ring sin string 內存 AS CP 給出一個N次函數,保證在範圍[l,r]內存在一點x,使得[l,x]上單調增,[x,r]上單調減。試求出x的值。 看代碼即可。 #include <cstdio>

P3382 模板

const tdi 好的 分法 pri cst max 。。 模擬退火 菜雞刷模板系列。。。 這道題其實是可以二分的,但是有更好的算法,叫做三分。 三分這種算法用於求單峰函數的最大值或者最小值。 算法思想就是弄\((l, r)\)區間的兩個三等分點,然後來縮小範圍。 因為這

數學

Definition 當一個函式\(f(x)\)滿足在區間在區間\([l,r]\)內有且僅有一個\(x~\in~[l,r]~,~s.t.~~f(x)\)在\([l,x]\)內單調嚴格遞增,在\([x,r]\)內單調嚴格遞減,則說\(f(x)\)在\([l,r]\)內是一個單峰函式,求出單峰點\(x\)的演算

演算法設計與資料結構:求單峰函式的極值

介紹 三分法的思路與二分法很類似,不過其用途沒有那麼廣泛,主要用於求單峰函式的極值。 示例程式碼 void Solve() { double left, right, m1, m2,

模板 (模板題:洛谷P3382)

題目描述 如題,給出一個N次函式,保證在範圍[l,r]記憶體在一點x,使得[l,x]上單調增,[x,r]上單調減。試求出x的值。 輸入輸出格式 輸入格式: 第一行一次包含一個正整數N和兩個實數l、r,含義如題目描述所示。 第二行包含N+1個實數,從高到低依次表示該

SCOI2010傳送帶答案

題目大意 平面上有兩條傳送帶,在上面行走有一定的速度,在平面其他地方行走有一定速度,求從一條傳送帶一端走到另一條一端的時間。 解題思路 顯然在兩條傳送帶都走一段後走平面,當一個轉折點確定後,距離就是一個單峰函式,可以用三分解決,總的就是三分套三

BZOJ 1857SCOI2010傳送帶

Description 在一個2維平面上有兩條傳送帶,每一條傳送帶可以看成是一條線段。兩條傳送帶分別為線段AB和線段CD。lxhgww在AB上的移動速度為P,在CD上的移動速度為Q,在平面上的移動速度R。現在lxhgww想從A點走到D點,他想知道最少需要走多長

洛谷P3382 模板

題目連結 方法1 就是三分的模板之前轉載過了就不寫了 不過求多項式有兩種效率不一樣的方法可以作為參考; //普通的求多項式 /*double F(double x){ double f=0; for(int i=n;i>=0;i--){

/函式先減後增/先增後減 Strange fuction HDU基礎04二分

Problem DescriptionNow, here is a fuction:  F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100)Can you find the minimum value when x

BZOJ 1857: [Scoi2010]傳送帶

膜一波PhDPhDPhD大佬啊~~ 三分兩個傳送帶的距離,然後相似算一下座標: #include <cmath> #include <cstdio> #include <cstring> #include <iostr

POJ - 3737 R - UmBasketella

POJ - 3737  R - UmBasketella  In recent days, people always design new things with multifunction. For instance, you can not only use cell

入門HDU - 4717 Q - The Moving Points

Q - The Moving Points  HDU - 4717 There are N points in total. Every point moves in certain direction and certain speed. We want to know a

貪心TCO2016R1B SettingShield

題意: 分析: 很顯然,以第一種方式的使用次數為自變數,以第二種方式的使用次數為因變數,一定是一個不上升函式。 換言之,已知f(x)為不下降函式,通過神奇的證明發現:f(x)+x為單谷函式。 所以。。。三分就行了第一種方式的使用次數就行了。。 求總方案可以用貪心的思想

Code Forces 320E+字首和Weakness and Poorness 最大的區間和的絕對值儘可能小

【題意】 給你一個整數數列a1~an 找到一個實數x,使得a1-x,a2-x,…,an-x的weakness儘可能小 一個數列的weakness,是這個數列所有區間poorness的最大值 一個區間的poorness,是這個區間內所有元素和的絕對值

查詢求單峰函式的最值 ZOJ 3386 Trick or Treat

         題目大意是:在一個平面上有N個點,每個點的座標已經給出,現在要求在X軸上找一個點,使得這個點到所有點中最大的距離最小。          分析:我們設這個點為X0,所求的距離為F(x),那麼對於所有的 X < X0 和 X > X0 都有F(x)