POJ 1921 Paper Cut(计算几何の折纸问题)
Description
Carol's puzzle is simple to state. She folds the paper in a certain manner and then uses a knife to cut through the folded paper. What Mike needs to do is to tell how many pieces the folded paper will turn into after it is cut. To eliminate the ambiguity, we can coordinate the paper as [0, 1] * [0, 1], with the coordinates of lower left corner (0, 0). A fold is denoted by two points (x1, y1) and (x2, y2) on the folding line, with which, the direction of the line is determined by from (x1, y1) to (x2, y2). Carol will always fold the paper from left to right relative to the directed line given (see Figure-1). The cut is determined by the two points on the cut line. Please note that the points given to determine the fold or the cut are not necessarily on the paper. 
Input
Output
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII; const double PI = acos(-1.0);
const double EPS = 1e-; inline int sgn(double x) {
return (x > EPS) - (x < -EPS);
} struct Point {
double x, y;
Point() {}
Point(double x, double y): x(x), y(y) {}
void read() {
scanf("%lf%lf", &x, &y);
}
Point operator + (const Point &rhs) const {
return Point(x + rhs.x, y + rhs.y);
}
Point operator - (const Point &rhs) const {
return Point(x - rhs.x, y - rhs.y);
}
Point operator * (double t) const {
return Point(x * t, y * t);
}
double length() const {
return sqrt(x * x + y * y);
}
Point unit() const {
double l = length();
return Point(x / l, y / l);
}
}; double dist(const Point &p1, const Point &p2) {
return (p1 - p2).length();
} Point rotate(const Point &p, double angle, const Point &o = Point(, )) {
Point t = p - o;
double x = t.x * cos(angle) - t.y * sin(angle);
double y = t.y * cos(angle) + t.x * sin(angle);
return Point(x, y) + o;
} double cross(const Point &a, const Point &b) {
return a.x * b.y - a.y * b.x;
} double cross(const Point &sp, const Point &ep, const Point &op) {
return cross(sp - op, ep - op);
} struct Seg {
Point st, ed;
Seg() {}
Seg(Point st, Point ed): st(st), ed(ed) {}
void read() {
st.read(); ed.read();
}
};
typedef Seg Line;
//return Ax + By + C =0 's A, B, C
void Coefficient(const Line &L, double &A, double &B, double &C) {
A = L.ed.y - L.st.y;
B = L.st.x - L.ed.x;
C = L.ed.x * L.st.y - L.st.x * L.ed.y;
}
//point of intersection
Point operator * (const Line &a, const Line &b) {
double A1, B1, C1;
double A2, B2, C2;
Coefficient(a, A1, B1, C1);
Coefficient(b, A2, B2, C2);
Point I;
I.x = - (B2 * C1 - B1 * C2) / (A1 * B2 - A2 * B1);
I.y = (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1);
return I;
} double Point_to_Line(const Point &p, const Line &L) {
return fabs(cross(p, L.st, L.ed)/dist(L.st, L.ed));
} Point reflection(const Point &p, const Line &l) {
Point t = rotate(l.ed - l.st, -PI / );
return p + t.unit() * ( * Point_to_Line(p, l));
} vector<Point> p_vec, p_buf; struct Poly {
vector<int> id;
void add(int i) {
id.push_back(i);
}
Point& operator [] (int i) const {
return p_vec[id[i]];
}
}; vector<Poly> pol_vec, pol_buf;
map<PII, int> edge_map; Point paper[] = {Point(, ), Point(, ), Point(, ), Point(, )}; void reflection(const Poly &pol, const Line &l) {
for(int i = ; i < int(pol.id.size()); ++i)
if(pol.id[i] < int(p_buf.size())) p_buf[pol.id[i]] = reflection(pol[i], l);
} int intersection(int id1, int id2, const Point &p1, const Point &p2) {
map<PII, int>::iterator it = edge_map.find(make_pair(id1, id2));
if(it == edge_map.end()) {
p_vec.push_back(Line(p_vec[id1], p_vec[id2]) * Line(p1, p2));
edge_map[make_pair(id1, id2)] = edge_map[make_pair(id1, id2)] = p_vec.size() - ;
return p_vec.size() - ;
} else return it->second;
} void fold(const Point &p1, const Point &p2, const Poly &pol) {
Poly res1, res2;
int last_s = sgn(cross(p1, pol[], p2));
for(int i = ; i < int(pol.id.size()); ++i) {
int now_s = sgn(cross(p1, pol[i], p2));
if(now_s == ) {
res1.add(pol.id[i]);
res2.add(pol.id[i]);
} else if(now_s < ) {
if(last_s > ) {
int k = intersection(pol.id[i - ], pol.id[i], p1, p2);
res1.add(k);
res2.add(k);
}
res1.add(pol.id[i]);
} else if(now_s > ) {
if(last_s < ) {
int k = intersection(pol.id[i - ], pol.id[i], p1, p2);
res1.add(k);
res2.add(k);
}
res2.add(pol.id[i]);
}
last_s = now_s;
}
if(res1.id.size() > ) {
res1.add(res1.id[]);
reflection(res1, Line(p1, p2));
reverse(res1.id.begin(), res1.id.end());
pol_buf.push_back(res1);
}
if(res2.id.size() > ) {
res2.add(res2.id[]);
pol_buf.push_back(res2);
}
} void fold(const Point &p1, const Point &p2) {
p_buf = p_vec;
edge_map.clear();
pol_buf.clear();
for(int i = ; i < int(pol_vec.size()); ++i)
fold(p1, p2, pol_vec[i]);
pol_vec = pol_buf;
for(int i = ; i < int(p_buf.size()); ++i)
p_vec[i] = p_buf[i];
} void dfs(vector<bool> &vis, int id, const Line &l) {
vis[id] = true;
Poly &pol = pol_vec[id];
for(int i = ; i < int(pol.id.size() - ); ++i) {
if(sgn(cross(l.ed, pol[i], l.st)) == && sgn(cross(l.ed, pol[i + ], l.st)) == ) continue;
int id1 = pol.id[i], id2 = pol.id[i + ];
for(int j = ; j < int(pol_vec.size()); ++j) {
if(vis[j]) continue;
for(int k = ; k < int(pol_vec[j].id.size() - ); ++k) {
if(pol_vec[j].id[k] == id1 && pol_vec[j].id[k + ] == id2) {
dfs(vis, j, l);
break;
}
}
}
}
} int cut(const Line &l) {
int ret = ;
vector<bool> vis(p_vec.size());
for(int i = ; i < int(pol_vec.size()); ++i) {
if(!vis[i]) {
dfs(vis, i, l);
++ret;
}
}
return ret;
} int main() {
int T;
scanf("%d", &T);
Poly init_pol;
for(int i = ; i <= ; ++i) init_pol.add(i & );
while(T--) {
int n;
scanf("%d", &n);
p_vec.clear();
pol_vec.clear();
for(int i = ; i < ; ++i) p_vec.push_back(paper[i]);
for(int i = ; i <= ; ++i) pol_vec.push_back(init_pol);
Point p1, p2;
for(int i = ; i <= n; ++i) {
p1.read(), p2.read();
fold(p1, p2);
}
printf("%d\n", cut(Line(p1, p2)));
}
}
POJ 1921 Paper Cut(计算几何の折纸问题)的更多相关文章
- 【BZOJ】1074: [SCOI2007]折纸origami
http://www.lydsy.com/JudgeOnline/problem.php?id=1074 题意:一开始有一个左上角是(0,100),右下角是(100,0)的纸片,现在可以沿有向直线折n ...
- 1074: [SCOI2007]折纸origami
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 372 Solved: 229[Submit][Status][Discuss] Descriptio ...
- 【题解】折纸 origami [SCOI2007] [P4468] [Bzoj1074]
[题解]折纸 origami [SCOI2007] [P4468] [Bzoj1074] 传送门:折纸 \(\text{origami [SCOI2007] [P4468]}\) \(\text{[B ...
- CSS3写折纸
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
- 折纸问题java实现
/** * 折纸问题 这段代码写的太low了 本人水平有限 哎... 全是字符串了 * @param n * @return * @date 2016-10-7 * @author shaobn */ ...
- 1074: [SCOI2007]折纸origami - BZOJ
Description 桌上有一张边界平行于坐标轴的正方形纸片,左下角的坐标为(0,0),右上角的坐标为(100,100).接下来执行n条折纸命令.每条命令用两个不同点P1(x1,y1)和P2(x2, ...
- CSS3实现文字折纸效果
CSS3实现文字折纸效果 效果图: 代码如下,复制即可使用: <!DOCTYPE html> <html> <head> <title></tit ...
- UVA 177 PaperFolding 折纸痕 (分形,递归)
著名的折纸问题:给你一张很大的纸,对折以后再对折,再对折……每次对折都是从右往左折,因此在折了很多次以后,原先的大纸会变成一个窄窄的纸条.现在把这个纸条沿着折纸的痕迹打开,每次都只打开“一半”,即把每 ...
- ZR#955 折纸
ZR#955 折纸 解法: 可以发现折纸之后被折到上面的部分实际上是没有用的,因为他和下面对应位置一定是一样的,而影响答案的只有每个位置的颜色和最底层的坐标范围.因此,我们只需要考虑最底层即可,即我们 ...
随机推荐
- grid 布局的使用
grid 布局的使用 css 网格布局,是一种二维布局系统. 浏览器支持情况:老旧浏览器不支持, 概念: 网格容器.元素应用dispalay:grid,它是所有网格项的父元素. <div cla ...
- 编程界失传秘术,SSO单点登录,什么是单点,如何实现登录?
单点登录 多系统,单一位置登录,实现多系统同时登录的一种技术. 常出现在互联网应用和企业级平台中. 如:京东. 单点登录一般是用于互相授信的系统,实现单一位置登录,全系统有效的. 三方登录:某系统,使 ...
- MySQL索引的使用及注意事项
索引是存储引擎用于快速找到记录的一种数据结构.索引优化应该是对查询性能优化最有效的手段了.索引能够轻易将查询性能提高几个数量级,"最优"的索引有时比一个"好的" ...
- DBUtils 学习使用
DBUtils 学习使用 commons-dbutils简介 commons-dbutils是Apache组织提供的一个开源JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbuti ...
- Django的MVT的思路
1.先上两张图片 2.我的理解 view在MVT框架里面,起到的是中间调度的作用. a.在diango里面有个关键性路径的配置 就是在django2.0前的url和在2.0后的path. 为避免一个项 ...
- angularjs中控制器之间的通信----$on、$emit和$broadcast解析
$on.$emit和$broadcast使得event.data在controller之间的传递变的简单. $emit只能向parent controller传递event与data $broadca ...
- Python学习:8.小项目之登录注册验证
简介 本次项目登录注册验证是对之前学习知识点的加深学习,这次项目的练习的知识点有函数.判断语句.循环语句.文件操作等. 项目流程 运行代码之后,输出登录或者注册选项. 当选择登录之后,输入用户名密码, ...
- golang 多维哈希(map,hashmap)实践随笔
有些场景使用多维哈希来存储数据,时间复杂度恒定,简单粗暴好用.这里记录一下. 如下是三维哈希的简单示意图,建议层数不要太多,否则时间久了,自己写的代码都不认识. 下图是三维哈希在内存的存储形式,has ...
- 在vue项目中添加eslint规则
自己配置脚手架时候如何安装eslint语法规则, 第一步安装 官方推荐的安装包如下 eslint eslint-config-standard eslint-plugin-standard eslin ...
- 20145207 ms08_067攻击实验
ms08_067攻击实验原理 实验过程 查看两台主机ip,并ping通 启动msf,查看关于ms08_067漏洞的基本信息 查看其可攻击的操作系统 查看可用载荷 查看需要设定的参数 修改LHOST(攻 ...