zoukankan      html  css  js  c++  java
  • 2017-2018 ACM-ICPC, NEERC, Moscow Subregional Contest J. Judging the Trick

    J. Judging the Trick
    time limit per test
    2.0 s
    memory limit per test
    512 MB
    input
    standard input
    output
    standard output

    Tricky Ricky is a world-famous magician. He even claims that he can overcome the laws of physics and geometry.

    In his latest trick he covers a w × h rectangle with n triangles fully contained within the rectangle. Sounds easy? But what would you say if he told you that the total area of those triangles is smaller than w·h?

    You are of that kind of people that are not very fun at parties and magic shows, so you want to prove him that this is impossible. Given a description of n triangles, find any point of the rectangle which does not belong to any triangle interior or border.

    Input

    The first line of the input contains three integers nw and h (1 ≤ n ≤ 100 000, 1 ≤ w, h ≤ 10 000) — the number of triangles and the dimensions of the rectangle.

    The following n lines contain descriptions of triangle vertices. Each line contains six integers xi, 1, yi, 1, xi, 2, yi, 2, xi, 3 and yi, 3(0 ≤ xi, j ≤ w0 ≤ yi, j ≤ h). It is guaranteed that all given triangles are non-degenerate, and the total area of triangles is smaller than w·h.

    Output

    Print two real numbers x and y (0 ≤ x ≤ w0 ≤ y ≤ h) defining the coordinates of a point that lies strictly outside of all of the triangles. The numbers should be printed as decimal fractions with at most 9 digits after decimal point. Note that usage of exponential format is not allowed. Your answer will be considered correct if the given point does not belong to any triangle interior or border. Please, note that your answer will be verified with no absolute or relative tolerance.

    It is guaranteed (by Euclid and some other guys) that such point always exists.

    Example
    input
    Copy
    5 4 3
    0 0 3 0 0 2
    3 3 0 1 0 3
    1 1 3 1 2 3
    3 0 4 0 4 3
    4 3 3 2 4 1
    output
    Copy
    1.1 1.6
    Note

    An illustration for the sample is given below.

    思路:题目保证了三角形面积和不超过矩形面积。四分矩形,必有一子矩形中面积超过该矩形与所有三角形面积交的和,求三角形和矩形面积交用的半平面交板子。四分一定次数后在子矩形内随机取点判断是否合法。

    程序中的trick:四个子矩形中随机选顺序判断,若子矩形面积差值超过大矩形面积差值四分之一,则进入该子矩形;

             四分过程中及时排除掉与当前矩形相交面积为0的三角形。

           随机选点之前也排除掉不可能在其上的三角形。

           不加这几个优化会T,调了92发才过,可能我的半平面交比较挫吧。

      1 #include <iostream>
      2 #include <fstream>
      3 #include <sstream>
      4 #include <cstdlib>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <queue>
     11 #include <stack>
     12 #include <vector>
     13 #include <set>
     14 #include <map>
     15 #include <list>
     16 #include <iomanip>
     17 #include <cctype>
     18 #include <cassert>
     19 #include <bitset>
     20 #include <ctime>
     21 
     22 using namespace std;
     23 
     24 #define pau system("pause")
     25 #define ll long long
     26 #define pii pair<int, int>
     27 #define pb push_back
     28 #define pli pair<ll, int>
     29 #define pil pair<int, ll>
     30 #define clr(a, x) memset(a, x, sizeof(a))
     31 
     32 const double pi = acos(-1.0);
     33 const int INF = 0x3f3f3f3f;
     34 const int MOD = 1e9 + 7;
     35 const double EPS = 1e-14;
     36 
     37 /*
     38 #include <ext/pb_ds/assoc_container.hpp>
     39 #include <ext/pb_ds/tree_policy.hpp>
     40 using namespace __gnu_pbds;
     41 #define TREE tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update>
     42 TREE T;
     43 */
     44 
     45 
     46 #define Double double
     47 
     48 int n;
     49 Double w, h;
     50 struct Point {
     51     Double x, y;
     52     Point () {}
     53     Point(Double x, Double y) : x(x), y(y) {}
     54     Point operator - (const Point &p) const {
     55         return Point(x - p.x, y - p.y);
     56     }
     57     Double operator ^ (const Point &p) const {
     58         return x * p.y - y * p.x;
     59     }
     60     void input() {
     61         double tx, ty;
     62         scanf("%lf%lf", &tx, &ty);
     63         x = tx, y = ty;
     64     }
     65 };
     66 struct Line {
     67     Point s, e;
     68     double k;
     69     Line () {}
     70     Line (Point _s, Point _e) {
     71         s = _s, e = _e;
     72         k = atan2(e.y - s.y, e.x - s.x);
     73     }
     74     Point operator & (const Line &b) const {
     75         Point res = s;
     76         double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
     77         res.x += (e.x - s.x) * t;
     78         res.y += (e.y - s.y) * t;
     79         return res;
     80     }
     81 };
     82 
     83 //左侧有效
     84 bool HPIcmp(Line a, Line b) {
     85     if (fabs(a.k - b.k) > EPS) return a.k < b.k;
     86     return ((a.s - b.s) ^ (b.e - b.s)) < 0;
     87 }
     88 
     89 bool onRightPL(Point p, Line l) {
     90     return ((p - l.s) ^ (l.e - l.s)) > EPS;
     91 }
     92 
     93 Line Q[22510];
     94 
     95 inline void HPI(Line line[], int n, Point res[], int &resn) {
     96     sort(line, line + n, HPIcmp);
     97     int tot = 0;
     98     for (int i = 1; i < n; ++i) {
     99         if (fabs(line[i].k - line[i - 1].k) > EPS) {
    100             line[++tot] = line[i];
    101         }
    102     }
    103     int head = 0, tail = 1;
    104     Q[0] = line[0]; Q[1] = line[1];
    105     for (int i = 2; i <= tot; ++i) {
    106         if (fabs((Q[tail].e - Q[tail].s) ^ (Q[tail - 1].e - Q[tail - 1].s)) < EPS || 
    107             fabs((Q[head].e - Q[head].s) ^ (Q[head + 1].e - Q[head + 1].s)) < EPS)
    108             return;
    109         while (head < tail && onRightPL(Q[tail] & Q[tail - 1], line[i])) --tail;
    110         while (head < tail && onRightPL(Q[head] & Q[head + 1], line[i])) ++head;
    111         Q[++tail] = line[i];
    112     }
    113     while (head < tail && onRightPL(Q[tail] & Q[tail - 1], Q[head])) --tail;
    114     while (head < tail && onRightPL(Q[head] & Q[head + 1], Q[tail])) ++head;
    115     if (tail <= head + 1) return;
    116     for (int i = head; i < tail; ++i) {
    117         res[resn++] = Q[i] & Q[i + 1];
    118     }
    119     if (head < tail - 1) res[resn++] = Q[tail] & Q[head];
    120 }
    121 inline double cal_S(Point p[], int resn) {
    122     double ans = 0;
    123     for (int i = 0; i < resn; ++i) {
    124         ans += p[i] ^ p[(i + 1) % resn];
    125     }
    126     return 0.5 * fabs(ans);
    127 }
    128 struct Tran {
    129     Point p[3];
    130     void input() {
    131         for (int i = 0; i < 3; ++i) {
    132             p[i].input();
    133         }
    134     }
    135     void modify() {
    136         double wx = (p[0].x + p[1].x + p[2].x) / 3;
    137         double wy = (p[0].y + p[1].y + p[2].y) / 3;
    138         if (onRightPL(Point(wx, wy), Line(p[0], p[1]))) {
    139             swap(p[0], p[2]);
    140         }
    141     }
    142     inline double S(double x1, double x2, double y1, double y2) {
    143         Line l[11];
    144         for (int i = 0; i < 3; ++i) {
    145             l[i] = Line(p[i], p[(i + 1) % 3]);
    146         }
    147         l[3] = Line(Point(x2, 0), Point(x2, 1));
    148         l[4] = Line(Point(x1, 1), Point(x1, 0));
    149         l[5] = Line(Point(0, y1), Point(1, y1));
    150         l[6] = Line(Point(1, y2), Point(0, y2));
    151         Point res[17]; int resn = 0;
    152         HPI(l, 7, res, resn);
    153         return cal_S(res, resn);
    154     }
    155 } t[100015];
    156 bool inTran(Point p, Tran t) {
    157     Double res1 = (p - t.p[0]) ^ (p - t.p[1]);
    158     Double res2 = (p - t.p[1]) ^ (p - t.p[2]);
    159     Double res3 = (p - t.p[2]) ^ (p - t.p[0]);
    160     if (fabs(res1) < EPS || fabs(res2) < EPS || fabs(res3) < EPS) return true;
    161     return res1 < -EPS && res2 < -EPS && res3 < -EPS || 
    162         res1 > EPS && res2 > EPS && res3 > EPS;
    163 }
    164 bool vis[100015], tvis[100015];
    165 bool ok(Point p) {
    166     for (int i = 1; i <= n; ++i) {
    167         if (vis[i]) continue;
    168         if (inTran(p, t[i])) return false;
    169     }
    170     return true;
    171 }
    172 double ok(double x1, double x2, double y1, double y2) {
    173     double s = 0;
    174     for (int i = 1; i <= n; ++i) {
    175         if (vis[i]) continue;
    176         double x = t[i].S(x1, x2, y1, y2);
    177         if (x < EPS) tvis[i] = 1;
    178         s += x;
    179     }
    180     return (y2 - y1) * (x2 - x1) - s;
    181 }
    182 const int dir[4][2] = {
    183     1, 1, 0, 1, 
    184     1, 0, 0, 0
    185 };
    186 bool online(Point p1, Point p2, Point p3) {
    187     double res = (p2 - p1) ^ (p3 - p1);
    188     if (fabs(res) > EPS) return false;
    189     double x1 = min(p2.x, p3.x), x2 = max(p2.x, p3.x);
    190     double y1 = min(p2.y, p3.y), y2 = max(p2.y, p3.y);
    191     return x1 <= p2.x && p2.x <= x2 && y1 <= p2.y && p2.y <= y2;
    192 }
    193 bool ok(int id, double x1, double x2, double y1, double y2) {
    194     if (t[id].S(x1, x2, y1, y2) > EPS) return false;
    195     for (int i = 0; i < 3; ++i) {
    196         if (online(t[id].p[i], Point(x1, y1), Point(x1, y2))) return false;
    197         if (online(t[id].p[i], Point(x1, y1), Point(x2, y1))) return false;
    198         if (online(t[id].p[i], Point(x2, y2), Point(x1, y2))) return false;
    199         if (online(t[id].p[i], Point(x2, y2), Point(x2, y1))) return false;
    200         if (online(Point(x1, y1), t[id].p[i], t[id].p[(i + 1) % 3])) return false;
    201         if (online(Point(x1, y2), t[id].p[i], t[id].p[(i + 1) % 3])) return false;
    202         if (online(Point(x2, y1), t[id].p[i], t[id].p[(i + 1) % 3])) return false;
    203         if (online(Point(x2, y2), t[id].p[i], t[id].p[(i + 1) % 3])) return false;
    204     }
    205     return true;
    206 }
    207 int main() {
    208     clock_t start = clock();
    209     srand((int)time(NULL));
    210     scanf("%d", &n);
    211     cin >> w >> h;
    212     for (int i = 1; i <= n; ++i) {
    213         t[i].input();
    214         t[i].modify();
    215     }    
    216     Double sx = 0, sy = 0, lx = w * 0.5, ly = h * 0.5;
    217     double deltas = w * h;
    218     for (int i = 1; i <= n; ++i) {
    219         deltas += ((t[i].p[2] - t[i].p[0]) ^ (t[i].p[1] - t[i].p[0])) / 2;
    220     }
    221     if (99978 == n) {
    222         //printf("%.12f
    ", deltas);
    223     }
    224     for (int rep = 1; rep <= 20; ++rep) {
    225         double tmp[4];    
    226         int id;
    227         int dd[4] = {0, 1, 2, 3};
    228         random_shuffle(dd, dd + 4);
    229         for (int i = 3; ~i; --i) {
    230             double tx = sx + lx * dir[dd[i]][0];
    231             double ty = sy + ly * dir[dd[i]][1];
    232             for (int i = 1; i <= n; ++i) tvis[i] = 0;
    233             tmp[i] = ok(tx, tx + lx, ty, ty + ly);
    234             if (tmp[i] >= 0.25 * deltas - EPS) {
    235                 id = dd[i];
    236                 for (int i = 1; i <= n; ++i) {
    237                     vis[i] |= tvis[i];
    238                 }
    239                 break;
    240             }
    241         }
    242         //int id = rand() % 4;
    243         for (int i = 0; i < 4; ++i) {
    244             //if (tmp[i] > tmp[id]) id = i;
    245         }
    246         sx = sx + dir[id][0] * lx;
    247         sy = sy + dir[id][1] * ly;
    248         lx *= 0.5, ly *= 0.5;
    249         deltas *= 0.25;
    250     }
    251     clock_t end = clock();
    252     if (99978 == n) {
    253         //return !printf("%.6f
    ", (double)(end - start) / CLOCKS_PER_SEC);
    254     }
    255     for (int i = 1; i <= n; ++i) {
    256         vis[i] = ok(i, sx, sx + lx * 2, sy, sy + ly * 2);
    257     }
    258     double Lx = lx, Ly = ly;
    259     for (int rep = 1; rep <= 100000; ++rep) {
    260         Double x = 1.0 * rand() / RAND_MAX * Lx * 2 + sx;
    261         Double y = 1.0 * rand() / RAND_MAX * Ly * 2 + sy;
    262         if (ok(Point(x, y))) {
    263             return !printf("%.9f %.9f
    ", (double)x, (double)y);
    264         }
    265     }
    266     printf("%.9f %.9f
    ", (double)(sx + lx), (double)(sy + ly));
    267     return 0;
    268 }
    View Code
  • 相关阅读:
    PHP使用数据库永久连接方式操作MySQL的是与非
    php生成xml文件
    Ruby学习之类
    新增题目功能模块总结
    Ruby学习之类2
    smarty section循环成两列的问题
    jQuery validate插件初探
    Zend Framework学习之Zend_Config
    Zend Framework学习之Zend_Loader动态加载文件和类
    JS 删除字符串最后一个字符的方法
  • 原文地址:https://www.cnblogs.com/BIGTOM/p/9754342.html
Copyright © 2011-2022 走看看