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

  • 相关阅读:
    13.解决SUSELinux用户登录Module is unknow问题
    12.解决SUSE Linux无法使用SSH登录的问题
    11.SUSE Linux服务器系统网卡配置重启问题
    02.Windows2012R2安装360安全卫士失败及无法卸载问题
    01.Windows2008R2系统禁启SMBv1服务命令
    07.SUSE Linux 系统本地yum源配置
    06.Linux-RedHat系统本地yum源配置
    05.Linux-CentOS系统本地Yum源搭建
    04.Linux-CentOS系统sudo权限配置
    03.LinuxCentOS系统root目录LVM磁盘扩容
  • 原文地址:https://www.cnblogs.com/LyonLys/p/poj_1514_Lyon.html
Copyright © 2011-2022 走看看