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. 洛谷P1002 过河卒 [2017年4月计划 动态规划15]

    P1002 过河卒 题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之 ...

  2. 【BZOJ2809】【APIO2012】dispatching

    左偏树. 每个子节点维护大根堆,遍历一个儿子就往自己合并,合并发现钱不够了就删除队顶. //Achen #include<algorithm> #include<iostream&g ...

  3. 存储过程详解 -SQLServer

    来源:http://www.cnblogs.com/knowledgesea/archive/2013/01/02/2841588.html 存储过程简介 什么是存储过程:存储过程可以说是一个记录集吧 ...

  4. iOS 7: 如何为iPhone 5s编译64位应用

    随着iPhone 5S的推出,大家开始关心5S上所使用的64位CPU A7. 除了关心A7的性能以外,大家还会关心一个问题,那就是使用A7的64位系统对应用有没有什么要求.特别是应用开发者,大家都比较 ...

  5. 微信小程序制作选项卡

    wxml: <view class="tab"><view class="tab-title" bindtap="tabFun&qu ...

  6. ATM系统和购物车系统 不需要文件支撑

    目录 ATM系统 购物车系统 ATM系统 #coding=utf8 #Version:python 3.6.4 #Tools:Python 2019.9.7 _data_ = '2019/9/7/01 ...

  7. Swift 之类的继承与类的访问权限

    http://www.cocoachina.com/swift/20160104/14821.html 上一篇博客<窥探Swift之别具一格的Struct和Class>的博客可谓是给Swi ...

  8. 如何在liferay 7 mvc-portlet中调用service-builder项目生成的service

    不想写了,贴大神帖子 https://web.liferay.com/web/zhao.jin/blog/-/blogs/creating-service-builder-mvc-portlet-in ...

  9. ie8 下margin-top失效的小案例

    一个小案例,是关于IE8下的margin-top的失效问题,巨日代码如下: 正常的chrome浏览器下的显示如下: margin-top=10px,正常显示 但是在ie8下,最终样式如下: margi ...

  10. kubernetes1.4新特性:增加新的节点健康状况类型DiskPressure

    背景资料 在Kubernetes架构图中可以看到,节点(Node)是一个由管理节点委托运行任务的worker. 它能运行一个或多个Pods,节点(Node)提供了运行容器环境所需要的所有必要条件,在K ...