zoukankan      html  css  js  c++  java
  • poj 1514 Metal Cutting (dfs+多边形切割)

    1514 -- Metal Cutting

      一道类似于半平面交的题。

      题意相当简单,给出一块矩形以及最后被切出来的的多边形各个顶点的位置。每次切割必须从一端切到另一端,问切出多边形最少要切多长的距离。

      因为最短的切割距离肯定是没有多余的切割痕迹的,而且对于多边形的每一条边,都需要至少经过一次,也就是这些是必要切割。又因为最多就只有8条切割的痕迹,所以我们可以枚举每条痕迹的先后次序,然后模拟切割即刻。复杂度O(n!*n)。

    代码如下:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cmath>
      4 #include <vector>
      5 #include <iostream>
      6 #include <algorithm>
      7 
      8 using namespace std;
      9 
     10 const double EPS = 1e-8;
     11 const double PI = acos(-1.0);
     12 template <class T> T sqr(T x) { return x * x;}
     13 struct Point {
     14     double x, y;
     15     Point() {}
     16     Point(double x, double y) : x(x), y(y) {}
     17 } ;
     18 typedef Point Vec;
     19 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);}
     20 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);}
     21 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);}
     22 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);}
     23 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
     24 bool operator < (Point a, Point b) { return sgn(a.x - b.x) < 0 || sgn(a.x - b.x) == 0 && a.y < b.y;}
     25 bool operator == (Point a, Point b) { return sgn(a.x - b.x) == 0 && sgn(a.y - b.y) == 0;}
     26 
     27 inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
     28 inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
     29 inline double dotDet(Point o, Point a, Point b) { return dotDet(a - o, b - o);}
     30 inline double crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);}
     31 inline double vecLen(Vec x) { return sqrt(dotDet(x, x));}
     32 inline Vec vecUnit(Vec x) { return x / vecLen(x);}
     33 inline Vec normal(Vec x) { return Vec(-x.y, x.x) / vecLen(x);}
     34 inline bool onSeg(Point x, Point a, Point b) { return sgn(crossDet(x, a, b)) == 0 && sgn(dotDet(x, a, b)) < 0;}
     35 
     36 int segIntersect(Point a, Point c, Point b, Point d) {
     37     Vec v1 = b - a, v2 = c - b, v3 = d - c, v4 = a - d;
     38     int a_bc = sgn(crossDet(v1, v2));
     39     int b_cd = sgn(crossDet(v2, v3));
     40     int c_da = sgn(crossDet(v3, v4));
     41     int d_ab = sgn(crossDet(v4, v1));
     42 //    cout << a_bc << ' ' << b_cd << ' ' << c_da << ' ' << d_ab << endl;
     43     if (a_bc * c_da > 0 && b_cd * d_ab > 0) return 1;
     44     if (onSeg(b, a, c) && c_da) return 2;
     45     if (onSeg(c, b, d) && d_ab) return 2;
     46     if (onSeg(d, c, a) && a_bc) return 2;
     47     if (onSeg(a, d, b) && b_cd) return 2;
     48     return 0;
     49 }
     50 
     51 Point lineIntersect(Point P, Vec v, Point Q, Vec w) {
     52     Vec u = P - Q;
     53     double t = crossDet(w, u) / crossDet(v, w);
     54     return P + v * t;
     55 }
     56 
     57 struct Poly {
     58     vector<Point> pt;
     59     Poly() { pt.clear();}
     60     ~Poly() {}
     61     Poly(vector<Point> &pt) : pt(pt) {}
     62     Point operator [] (int x) const { return pt[x];}
     63     int size() { return pt.size();}
     64 } ;
     65 
     66 Poly cutPoly(Poly &poly, Point a, Point b) {
     67     Poly ret = Poly();
     68     int n = poly.size();
     69     for (int i = 0; i < n; i++) {
     70         Point c = poly[i], d = poly[(i + 1) % n];
     71         if (sgn(crossDet(a, b, c)) >= 0) ret.pt.push_back(c);
     72         if (sgn(crossDet(b - a, c - d)) != 0) {
     73             Point ip = lineIntersect(a, b - a, c, d - c);
     74             if (onSeg(ip, c, d)) ret.pt.push_back(ip);
     75         }
     76     }
     77     return ret;
     78 }
     79 
     80 const double dir[4][2] = { {0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}};
     81 const double FINF = 1e100;
     82 bool vis[10];
     83 Point rec[10];
     84 double minLen;
     85 
     86 void dfs(int p, int n, Poly &poly, double len) {
     87 //    for (int i = 0; i < n; i++) cout << vis[i]; cout << endl;
     88     if (p >= n) {
     89         minLen = min(len, minLen);
     90         return ;
     91     }
     92     for (int i = 0; i < n; i++) {
     93 //        cout << i << endl;
     94         if (vis[i]) continue;
     95         vis[i] = true;
     96         Vec d = vecUnit(rec[(i + 1) % n] - rec[i]) * 500.0;
     97 //        cout << rec[(i + 1) % n].x << ' ' << rec[(i + 1) % n].y << " !!! " << rec[i].x << ' ' << rec[i].y << endl;
     98 //        cout << d.x << ' ' << d.y << endl;
     99         Point s = rec[(i + 1) % n] + d, t = rec[i] - d;
    100         vector<Point> ip;
    101         ip.clear();
    102         for (int j = 0, sz = poly.size(); j < sz; j++) {
    103             if (segIntersect(s, t, poly[j], poly[(j + 1) % sz])) {
    104                 ip.push_back(lineIntersect(s, t - s, poly[j], poly[(j + 1) % sz] - poly[j]));
    105 //                cout << "has one" << endl;
    106             }
    107         }
    108         sort(ip.begin(), ip.end());
    109         int cnt = (int) (unique(ip.begin(), ip.end()) - ip.begin());
    110         if (cnt != 2) {
    111             puts("shit!!");
    112             while (1) {}
    113         }
    114         Poly tmp = cutPoly(poly, s, t);
    115         dfs(p + 1, n, tmp, len + vecLen(ip[0] - ip[1]));
    116         vis[i] = false;
    117     }
    118 }
    119 
    120 int main() {
    121 //    freopen("in", "r", stdin);
    122     double x, y;
    123     int n;
    124     while (cin >> x >> y) {
    125         Poly tmp = Poly();
    126         for (int i = 0; i < 4; i++) tmp.pt.push_back(Point(dir[i][0] * x, dir[i][1] * y));
    127         memset(vis, false, sizeof(vis));
    128         cin >> n;
    129         for (int i = 0; i < n; i++) cin >> rec[i].x >> rec[i].y;
    130         minLen = FINF;
    131         dfs(0, n, tmp, 0.0);
    132         printf("Minimum total length = %.3f
    ", minLen);
    133     }
    134     return 0;
    135 }
    View Code

    ——written by Lyon

  • 相关阅读:
    Leetcode 349. Intersection of Two Arrays
    hdu 1016 Prime Ring Problem
    map 树木品种
    油田合并
    函数学习
    Leetcode 103. Binary Tree Zigzag Level Order Traversal
    Leetcode 102. Binary Tree Level Order Traversal
    Leetcode 101. Symmetric Tree
    poj 2524 Ubiquitous Religions(宗教信仰)
    pat 1009. 说反话 (20)
  • 原文地址:https://www.cnblogs.com/LyonLys/p/poj_1514_Lyon.html
Copyright © 2011-2022 走看看