二分法只适用与线性函数,当函数脱离线性而呈现凸性或者凹性的时候,三分是很有必要的。
三分过程如下图:
凸函数:
凹函数:
实现方法:
double Calc(double p) {/*...*/ }double Solve(double MIN, double MAX) {double Left, Right;double mid, midmid;double mid_area = 0, midmid_area = 0; //***Left = MIN; Right = MAX;while (Left + eps < Right) {mid = (Left + Right) / 2;midmid = (mid + Right) / 2;mid_area = Calc(mid);midmid_area = Calc(midmid);if (midmid_area - mid_area > eps) Right = midmid;else Left = mid;}return mid_area; }
例题:HDU 4355 ( Party All the Time )
View Code
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <ctime> #include <queue> #include <map> #include <sstream>#define CL(arr, val) memset(arr, (val), sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) ((l) + (r)) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) ((x) > 0 ? (x) : -(x))typedef long long LL; const double eps = 1e-6; const double inf = 1000000000;using namespace std;const int N = 50010;struct node {double p;double w; } q[N];int n;double Calc(double p) {double tmp = 0, d;for(int i = 0; i < n; ++i) {d = abs(q[i].p - p);tmp += d*d*d*q[i].w;}return tmp; }double Solve(double MIN, double MAX) {double Left, Right;double mid, midmid;double mid_area = 0, midmid_area = 0;Left = MIN; Right = MAX;while (Left + eps < Right) {mid = (Left + Right) / 2;midmid = (mid + Right) / 2;mid_area = Calc(mid);midmid_area = Calc(midmid);if (midmid_area - mid_area > eps) Right = midmid;else Left = mid;}//printf("%.10f\n", mid_area);return mid_area; }int main() {//freopen("data.in", "r", stdin);int t, j, cas = 0;double mx, mi;scanf("%d", &t);while(t--) {scanf("%d", &n);mx = -inf, mi = inf;for(j = 0; j < n; ++j) {scanf("%lf%lf", &q[j].p, &q[j].w);if(mx < q[j].p) mx = q[j].p;if(mi > q[j].p) mi = q[j].p;}double ans = Solve(mi, mx) + 0.5;printf("Case #%d: %d\n", ++cas, int(ans));}return 0; }
POJ 3301
方法,对坐标系进行(0, 180]度的旋转,然后每个点得到新的坐标,找到最上面,最下面,最左面和最右面的点,然后就行确定当前旋转角度的面积。
x' = x*cos(th) + y*sin(th);
y' = y*cos(th) - x*sin(th);
View Code
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue>#define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("data.out", "w", stdout);typedef long long LL; const double eps = 1e-8; const double pi = acos(-1.0); const double inf = ~0u>>2;using namespace std;const int N = 50;struct node {double x, y; }p[N];int n;double Calc(double th) {double l = inf, r = -inf, d = inf, u = -inf;double xx, yy, t;for(int i = 0; i < n; ++i) {t = th*pi/180.0;xx = p[i].x*cos(t) + p[i].y*sin(t);yy = p[i].y*cos(t) - p[i].x*sin(t);l = min(l, xx); d = min(d, yy);r = max(r, xx); u = max(u, yy);}return max((r - l)*(r - l), (u - d)*(u - d)); }double Solve(double MIN, double MAX) {double Left, Right;double mid, midmid;double mid_area = 0, midmid_area = 0;Left = MIN, Right = MAX;while(Left + eps < Right) {mid = (Left + Right) / 2.0;midmid = (mid + Right) / 2.0;mid_area = Calc(mid);midmid_area = Calc(midmid);if(midmid_area - mid_area > eps) Right = midmid;else Left = mid;}return mid_area; }int main() {//Read();int T, i;scanf("%d", &T);while(T--) {scanf("%d", &n);for(i = 0; i < n; ++i) scanf("%lf%lf", &p[i].x, &p[i].y);printf("%.2f\n", Solve(0, 180));}return 0; }