1514 -- Metal Cutting

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

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

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

代码如下:

 #include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm> using namespace std; const double EPS = 1e-;
const double PI = acos(-1.0);
template <class T> T sqr(T x) { return x * x;}
struct Point {
double x, y;
Point() {}
Point(double x, double y) : x(x), y(y) {}
} ;
typedef Point Vec;
Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);}
Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);}
Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);}
Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);}
inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
bool operator < (Point a, Point b) { return sgn(a.x - b.x) < || sgn(a.x - b.x) == && a.y < b.y;}
bool operator == (Point a, Point b) { return sgn(a.x - b.x) == && sgn(a.y - b.y) == ;} inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
inline double dotDet(Point o, Point a, Point b) { return dotDet(a - o, b - o);}
inline double crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);}
inline double vecLen(Vec x) { return sqrt(dotDet(x, x));}
inline Vec vecUnit(Vec x) { return x / vecLen(x);}
inline Vec normal(Vec x) { return Vec(-x.y, x.x) / vecLen(x);}
inline bool onSeg(Point x, Point a, Point b) { return sgn(crossDet(x, a, b)) == && sgn(dotDet(x, a, b)) < ;} int segIntersect(Point a, Point c, Point b, Point d) {
Vec v1 = b - a, v2 = c - b, v3 = d - c, v4 = a - d;
int a_bc = sgn(crossDet(v1, v2));
int b_cd = sgn(crossDet(v2, v3));
int c_da = sgn(crossDet(v3, v4));
int d_ab = sgn(crossDet(v4, v1));
// cout << a_bc << ' ' << b_cd << ' ' << c_da << ' ' << d_ab << endl;
if (a_bc * c_da > && b_cd * d_ab > ) return ;
if (onSeg(b, a, c) && c_da) return ;
if (onSeg(c, b, d) && d_ab) return ;
if (onSeg(d, c, a) && a_bc) return ;
if (onSeg(a, d, b) && b_cd) return ;
return ;
} Point lineIntersect(Point P, Vec v, Point Q, Vec w) {
Vec u = P - Q;
double t = crossDet(w, u) / crossDet(v, w);
return P + v * t;
} struct Poly {
vector<Point> pt;
Poly() { pt.clear();}
~Poly() {}
Poly(vector<Point> &pt) : pt(pt) {}
Point operator [] (int x) const { return pt[x];}
int size() { return pt.size();}
} ; Poly cutPoly(Poly &poly, Point a, Point b) {
Poly ret = Poly();
int n = poly.size();
for (int i = ; i < n; i++) {
Point c = poly[i], d = poly[(i + ) % n];
if (sgn(crossDet(a, b, c)) >= ) ret.pt.push_back(c);
if (sgn(crossDet(b - a, c - d)) != ) {
Point ip = lineIntersect(a, b - a, c, d - c);
if (onSeg(ip, c, d)) ret.pt.push_back(ip);
}
}
return ret;
} const double dir[][] = { {0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}};
const double FINF = 1e100;
bool vis[];
Point rec[];
double minLen; void dfs(int p, int n, Poly &poly, double len) {
// for (int i = 0; i < n; i++) cout << vis[i]; cout << endl;
if (p >= n) {
minLen = min(len, minLen);
return ;
}
for (int i = ; i < n; i++) {
// cout << i << endl;
if (vis[i]) continue;
vis[i] = true;
Vec d = vecUnit(rec[(i + ) % n] - rec[i]) * 500.0;
// cout << rec[(i + 1) % n].x << ' ' << rec[(i + 1) % n].y << " !!! " << rec[i].x << ' ' << rec[i].y << endl;
// cout << d.x << ' ' << d.y << endl;
Point s = rec[(i + ) % n] + d, t = rec[i] - d;
vector<Point> ip;
ip.clear();
for (int j = , sz = poly.size(); j < sz; j++) {
if (segIntersect(s, t, poly[j], poly[(j + ) % sz])) {
ip.push_back(lineIntersect(s, t - s, poly[j], poly[(j + ) % sz] - poly[j]));
// cout << "has one" << endl;
}
}
sort(ip.begin(), ip.end());
int cnt = (int) (unique(ip.begin(), ip.end()) - ip.begin());
if (cnt != ) {
puts("shit!!");
while () {}
}
Poly tmp = cutPoly(poly, s, t);
dfs(p + , n, tmp, len + vecLen(ip[] - ip[]));
vis[i] = false;
}
} int main() {
// freopen("in", "r", stdin);
double x, y;
int n;
while (cin >> x >> y) {
Poly tmp = Poly();
for (int i = ; i < ; i++) tmp.pt.push_back(Point(dir[i][] * x, dir[i][] * y));
memset(vis, false, sizeof(vis));
cin >> n;
for (int i = ; i < n; i++) cin >> rec[i].x >> rec[i].y;
minLen = FINF;
dfs(, n, tmp, 0.0);
printf("Minimum total length = %.3f\n", minLen);
}
return ;
}

——written by Lyon

poj 1514 Metal Cutting (dfs+多边形切割)的更多相关文章

  1. poj 1474 Video Surveillance - 求多边形有没有核

    /* poj 1474 Video Surveillance - 求多边形有没有核 */ #include <stdio.h> #include<math.h> const d ...

  2. POJ 2378 Tree Cutting 3140 Contestants Division (简单树形dp)

    POJ 2378 Tree Cutting:题意 求删除哪些单点后产生的森林中的每一棵树的大小都小于等于原树大小的一半 #include<cstdio> #include<cstri ...

  3. 任意多边形切割/裁剪(附C#代码实现)

    本实现主要参考了发表于2003年<软件学报>的<一个有效的多边形裁剪算法>(刘勇奎,高云,黄有群)这篇论文,所使用的理论与算法大都基于本文,对论文中部分阐述进行了详细解释,并提 ...

  4. C# 实现 任意多边形切割折线算法

    1.    内容简介 本文旨在解决任意多边形切割折线,获取切割之后的折线集合. 本文实现的算法内容包括:判断两条线段是否相交,如若相交,获取交点集合.对线上的点集,按斜率方向排序.判断点是否在多边形内 ...

  5. POJ 1321 棋盘问题 --- DFS

    POJ 1321 题目大意:给定一棋盘,在其棋盘区域放置棋子,需保证每行每列都只有一颗棋子. (注意 .不可放 #可放) 解题思路:利用DFS,从第一行开始依次往下遍历,列是否已经放置棋子用一个数组标 ...

  6. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  7. [ACM_几何] Metal Cutting(POJ1514)半平面割与全排暴力切割方案

    Description In order to build a ship to travel to Eindhoven, The Netherlands, various sheet metal pa ...

  8. POJ 2378 Tree Cutting (DFS)

    题目链接:http://poj.org/problem?id=2378 一棵树,去掉一个点剩下的每棵子树节点数不超过n/2.问有哪些这样的点,并按照顺序输出. dfs回溯即可. //#pragma c ...

  9. poj 1416 Shredding Company( dfs )

    我的dfs真的好虚啊……,又是看的别人的博客做的 题目== 题目:http://poj.org/problem?id=1416 题意:给你两个数n,m;n表示最大数,m则是需要切割的数. 切割m,使得 ...

随机推荐

  1. 两张图搞清composer install与update区别 - 今日头条(www.toutiao.com)

    composer update : 主要是在开发阶段使用,根据我们在composer.json文件中指定的内容升级项目的依赖包. composer install : 主要是在部署阶段使用,以便在生产 ...

  2. 使用openpyxl模块时出现错误: zipfile.BadZipFile: File is not a zip file

    通过Pycharm工具新建一个xlsx文件. 再通过openpyxl模块读取该表时,报错: zipfile.BadZipFile: File is not a zip file 如下所示: 解决办法: ...

  3. NYoj 155最短路

    //dij #include<stdio.h> #include<string.h> #include<queue> using namespace std; #d ...

  4. 学习笔记(3)---安装SVM问题及解决方法

    1. LibSVM下载,安装 下载地址:http://www.csie.ntu.edu.tw/~cjlin/libsvm/,最新的版本是3.17 2. 入门 [heart_scale_label,he ...

  5. Ajax中post方法400和404的问题

    1.从400变成404 我相信有很多人都用过Ajax技术来获取数据,一般都是使用get来获取的,但是敏感信息就不能继续用get了,于是就换成了post,但是用post的时候有时候发生一些奇怪的事情,比 ...

  6. StringUtils常用方式留存

    StringUtils是org.apache.commons.lang下的一个工具包.主要用途从名字可以看出是针对于String的一些操作工具,里面包含的方法非常多,英语水平尚可以的人可以前往它的官方 ...

  7. 电影的微信小程序

    最近,工作没有那么忙,学习了一下小程序开发,感觉上手比较简单. 在项目中学习是最好的方式,于是就自己模仿豆瓣电影开发一款微信小程序版的豆瓣电影 准备工作: 数据来源:豆瓣电影API 功能: 电影榜单列 ...

  8. BZOJ 4817数点涂色题解

    题目链接 考试考了一道类似的题目,然后不争气的挂掉了,于是跑过来学习这道题的解法... 我还是太菜了.... 我们可以发现任意时刻,原树中颜色相同的点的集合一定是一条链, 即上面这种状态,而这种结构是 ...

  9. mysql更改密码

    mysql command line client输入密码以后闪退问题的解决: 网上搜到的解决办法(my.ini文件之类的修改对我都没有起到作用).. 所以觉得是自己密码的问题,因为许久不用这个软件了 ...

  10. vsync信号产生与分发

    以下分析基于android 4.4代码 vsync信号的产生.分发涉及到以下几个类,先主要了解下他们各自的功能: HWComposer:产生hardware vsync,post fb VSyncTh ...