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 折纸 解法: 可以发现折纸之后被折到上面的部分实际上是没有用的,因为他和下面对应位置一定是一样的,而影响答案的只有每个位置的颜色和最底层的坐标范围.因此,我们只需要考虑最底层即可,即我们 ...
随机推荐
- ABAP术语-R/3 Repository Information System
R/3 Repository Information System 原文:http://www.cnblogs.com/qiangsheng/archive/2008/03/11/1100076.ht ...
- Zabbix——部署(DB与web分离)
前提条件: 两台centos7设备 两台设备可以相互访问 Zabbix-Servser版本为4.0 mysql版本为8.0 关闭防火墙 Zabbix部署(包含server,web,agent) rpm ...
- 在控制台中操作MYSQL数据库步骤以及一些小问题
一直用Navicat来对MySQL数据库进行操作,今天突然想试试用DOS控制台来操作,特记录自己第一次使用经历,若有错误之处,还望大佬们指点. 首先打开控制台,win+R键,输入cmd,确定 输入my ...
- Python模块、包、异常、文件(案例)
Python模块.包.异常.文件(案例) python.py #模块 # Python中的模块(Module),是一个Python文件,以.py文件结尾,包含了Python对象定义和Python语句, ...
- TinyMCE插件:Filemanager [4.x-6.x] 文件名统一格式化
上传图片程序(filemanager/upload.php) 在if (!empty($_FILES) && $upload_files)中上传图片时,在文件正式上传至服务器前,有一次 ...
- 详解 Python3 正则表达式(二)
上一篇:详解 Python3 正则表达式(一) 本文翻译自:https://docs.python.org/3.4/howto/regex.html 博主对此做了一些批注和修改 ^_^ 使用正则表达式 ...
- title中添加小图标
<title>标签中不能添加图片,但是可以添加小图标. 步骤: 1.做一个16 X 16像素的ico格式的图标.具体操作方法是,先在Photoshop中做一个透明背景的16 X 16像素P ...
- 关于Json.dumos中的ensure_ascii
在使用json,dumps时,当需要输出中文时,需要在后面添加 ensure_ascii = Fasle 因为json.dumps 序列化时,默认对中文使用的是 ascii 编码,添加后才能输出中文 ...
- 使用cgroups来控制磁盘IO带宽
磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面:PostgreSQL内部结构与源代码研究索引页 回到顶级页面:PostgreSQL索引页 [作者 高健@博客园 luckyjackga ...
- 成都Uber优步司机奖励政策(3月18日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...