Description

Still remember those games we played in our childhood? Folding and cutting paper must be among the most popular ones. Clever children will always search for something new, even when they play games like cutting paper. Now, Carol, a smart girl, asks her brother Mike to solve a puzzle. However, as always, Mike cannot find the solution, therefore he turns to you for help.

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

The first line of the input contains one integer t, the number of test cases. Then t cases follow. For each test case, the first line consists of an integer N (0 <= N <= 20), the number of folds, and the following N lines give two points on each fold line as x1, y1, x2, y2. The following line gives two points on the cut line in the same way.

Output

For each test case, output one line containing the number of pieces the paper will turn into after the cut.
 
题目大意:给一张正方形的纸,沿给出的n条线折叠n次,然后沿一条线切开,问切开后有多少张纸。(估计在折痕上切也可以把折痕切开)
主要是要理解上面所说的 本质不同的点。所谓本质不同的点,包括有两点虽然拥有同一个坐标,但是它们实际上是这张纸不同的点。
还有上面没有提到的,关于切割的时候,再折叠一次再切。
 
PS:好难……
 
代码(16MS):
 #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(计算几何の折纸问题)的更多相关文章

  1. 【BZOJ】1074: [SCOI2007]折纸origami

    http://www.lydsy.com/JudgeOnline/problem.php?id=1074 题意:一开始有一个左上角是(0,100),右下角是(100,0)的纸片,现在可以沿有向直线折n ...

  2. 1074: [SCOI2007]折纸origami

    Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 372  Solved: 229[Submit][Status][Discuss] Descriptio ...

  3. 【题解】折纸 origami [SCOI2007] [P4468] [Bzoj1074]

    [题解]折纸 origami [SCOI2007] [P4468] [Bzoj1074] 传送门:折纸 \(\text{origami [SCOI2007] [P4468]}\) \(\text{[B ...

  4. CSS3写折纸

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  5. 折纸问题java实现

    /** * 折纸问题 这段代码写的太low了 本人水平有限 哎... 全是字符串了 * @param n * @return * @date 2016-10-7 * @author shaobn */ ...

  6. 1074: [SCOI2007]折纸origami - BZOJ

    Description 桌上有一张边界平行于坐标轴的正方形纸片,左下角的坐标为(0,0),右上角的坐标为(100,100).接下来执行n条折纸命令.每条命令用两个不同点P1(x1,y1)和P2(x2, ...

  7. CSS3实现文字折纸效果

    CSS3实现文字折纸效果 效果图: 代码如下,复制即可使用: <!DOCTYPE html> <html> <head> <title></tit ...

  8. UVA 177 PaperFolding 折纸痕 (分形,递归)

    著名的折纸问题:给你一张很大的纸,对折以后再对折,再对折……每次对折都是从右往左折,因此在折了很多次以后,原先的大纸会变成一个窄窄的纸条.现在把这个纸条沿着折纸的痕迹打开,每次都只打开“一半”,即把每 ...

  9. ZR#955 折纸

    ZR#955 折纸 解法: 可以发现折纸之后被折到上面的部分实际上是没有用的,因为他和下面对应位置一定是一样的,而影响答案的只有每个位置的颜色和最底层的坐标范围.因此,我们只需要考虑最底层即可,即我们 ...

随机推荐

  1. mysql主从延迟复制

    需求描述 正常情况下我们是不会有刻意延迟从库的需求的,因为正常的线上业务自然是延迟越低越好.但是针对测试场景,业务上偶尔需要测试延迟场景下业务是否能正常运行. 解决方案 针对这种场景mysql有一个叫 ...

  2. 用sqldeveloper连接数据库

    用sql developer连接sqlserver,连接窗口默认没有sqlsever页签,需要配置数据库驱动: 具体步骤: 1.工具--首选项--数据库--第三方JDBC驱动

  3. 原生JS实现移动端的轮播效果

    首先 我们想实现的效果是在手指按下拖动的时候图片能够跟随移动(无动画效果)然后松开手指后判断图片移动的位置 和某一个值进行比较 在这里我们默认定为盒子的1/3宽度 当x轴的移动位置大于1/3的时候图片 ...

  4. 自添加LUCI菜单及编译为ipk

    目录 添加汉化编译为ipk配置文件入口函数界面文件Makefile 添加 添加自己的luci界面,有3个必要的要素: a配置文件.新建一个在/etc/config/abcdefg b入口函数.新建一个 ...

  5. python学习第三天 -----2019年4月23日

    第三周-第03章节-Python3.5-集合及其运算 集合是一个无序的,不重复的数据组合,它的主要作用如下: 去重,把一个列表变成集合,就自动去重了 关系测试,测试两组数据之前的交集.差集.并集等关系 ...

  6. 第二节 双向链表的GO语言实现

    一.什么是双向链表 和单链表比较,双向链表的元素不但知道自己的下线,还知道自己的上线(越来越像传销组织了).小煤车开起来,图里面可以看出,每个车厢除了一个指向后面车厢的箭头外,还有一个指向前面车厢的箭 ...

  7. vs2013工程配置

    1. 目标文件生成路径配置: 直接改在工程同级目录下 x64\debug目录下: 2. 调试工程路径配置: 命令-----参照物为工程 工作目录----参照物为运行程序 3.  拷贝工程: bat的写 ...

  8. 高斯消元c++(非常暴力)

    暴力方法(已更新): #include<iostream> using namespace std; const int maxn = 1000; int n; double a[maxn ...

  9. 使用 Linux 下的的logrotate进行日志的切割

    实际生产中,使用一个log文件来记录所有信息的话,一方面,时间过久,就会占用很大的空间:另一方面,就是一个文件记录对于后期日志的查看非常不利.为了解决查看了一下资料,发现linux里面有一个logro ...

  10. Java设计模式(14)——行为模式之不变模式(Immutable)

    一.概述 概念 分类:弱不变模式(子类可变)和强不变模式(子类也是不可变) 应用场景 java.lang.String是一个经典的强不变类 二.分析 与享元模式的关系