【题解】折纸 origami [SCOI2007] [P4468] [Bzoj1074]
【题解】折纸 origami [SCOI2007] [P4468] [Bzoj1074]
传送门:折纸 \(\text{origami [SCOI2007] [P4468]}\) \(\text{[Bzoj1074]}\)
【题目描述】
初始有一个 \(100*100\) 的正方形纸片,现给出 \(n\) \((0 \leqslant n \leqslant 8)\) 条直线,将该纸片依次按照直线进行折叠,结束后会给出 \(m\) 个询问,每次询问求某个坐标上的点穿过了几层纸。
【分析】
又是一道毒瘤膜您题。
由于数据范围较小,可以直接上暴力。
考虑记录当前已有的多边形(初始为一个 \(100*100\) 的正方形),每折叠一次就把折叠线所穿过的所有多边形分成左右两部分,然后将右边部分的点全部关于折叠线对称,得到两个新的小多边形。
对于每次询问,暴力枚举统计 包含询问点的多边形 即可。
折叠 \(n\) 次后最多会出现 \(2^n\) 个多边形,每个多边形最多有 \(n^2\) 个点,射线法做一次 \(PIP\) 为 \(O(n^2)\),总时间复杂度为: \(O(m n^2 2^n)\) 。
注意:如果用的是 \(double\) 而不是 \(long\ double\),\(eps\) 开得过于小会导致答案出锅。
【Code】
#include<algorithm>
#include<cstdio>
#include<cmath>
#define LD double
#define LL long long
#define Re register int
#define Vector Point
using namespace std;
const int N=8;
const LD eps=1e-8;
inline int dcmp(LD a){return a<-eps?-1:(a>eps?1:0);}//处理精度
inline LD Abs(LD a){return a*dcmp(a);}//取绝对值
struct Point{
LD x,y;Point(LD X=0,LD Y=0){x=X,y=Y;}
inline void in(){scanf("%lf%lf",&x,&y);}
inline void out(){printf("%.2lf %.2lf\n",x,y);}
};
inline LD Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}//【点积】
inline LD Cro(Vector a,Vector b){return a.x*b.y-a.y*b.x;}//【叉积】
inline LD Len(Vector a){return sqrt(Dot(a,a));}//【模长】
inline LD Angle(Vector a,Vector b){return acos(Dot(a,b)/Len(a)/Len(b));}//【两向量夹角】
inline Vector operator+(Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
inline Vector operator-(Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}
inline Vector operator*(Vector a,LD b){return Vector(a.x*b,a.y*b);}
inline bool operator==(Point a,Point b){return !dcmp(a.x-b.x)&&!dcmp(a.y-b.y);}//两点坐标重合则相等
inline int pan_PL(Point p,Point a,Point b){//【判断点P是否在线段AB上】
return !dcmp(Cro(p-a,b-a))&&dcmp(min(a.x,b.x)-p.x)<=0&&dcmp(p.x-max(a.x,b.x))<=0&&dcmp(min(a.y,b.y)-p.y)<=0&&dcmp(p.y-max(a.y,b.y))<=0;
//PA,AB共线且P在AB之间
}
inline int pan_PL_(Point p,Point a,Point b){//【判断点P是否在直线AB上】
return !dcmp(Cro(p-a,b-a));//PA,AB共线
}
inline Point FootPoint(Point p,Point a,Point b){//【点P到直线AB的垂足】
Vector x=p-a,y=p-b,z=b-a;
LD len1=Dot(x,z)/Len(z),len2=-1.0*Dot(y,z)/Len(z);//分别计算AP,BP在AB,BA上的投影
return a+z*(len1/(len1+len2));//点A加上向量AF
}
inline Point Symmetry_PL(Point p,Point a,Point b){//【点P关于直线AB的对称点】
return p+(FootPoint(p,a,b)-p)*2;//将PF延长一倍即可
}
inline Point cross_LL(Point a,Point b,Point c,Point d){//【两直线AB,CD的交点】
Vector x=b-a,y=d-c,z=a-c;
return a+x*(Cro(y,z)/Cro(x,y));//点A加上向量AF
}
inline int pan_cross_L_L(Point a,Point b,Point c,Point d){//【判断直线AB与线段CD是否相交】
return pan_PL(cross_LL(a,b,c,d),c,d);//直线AB与直线CD的交点在线段CD上
}
inline int PIP(Point *P,Re n,Point a){//【射线法】判断点A是否在任意多边形Poly以内
Re cnt=0;LD tmp;
for(Re i=1;i<=n;++i){
Re j=i<n?i+1:1;
if(pan_PL(a,P[i],P[j]))return 2;//点在多边形上
if(a.y>=min(P[i].y,P[j].y)&&a.y<max(P[i].y,P[j].y))//纵坐标在该线段两端点之间
tmp=P[i].x+(a.y-P[i].y)/(P[j].y-P[i].y)*(P[j].x-P[i].x),cnt+=dcmp(tmp-a.x)>0;//交点在A右方
}
return cnt&1;//穿过奇数次则在多边形以内
}
inline int judge(Point a,Point L,Point R){//判断AL是否在AR右边
return dcmp(Cro(L-a,R-a))>0;
}
struct Poly{int n;Point P[N*N+3];}Py[(1<<N)+3],Qy[(1<<N)+3];
int n,t,tt,T;Point a,b;
inline void sakura(Poly Po,Point a,Point b){
Poly L,R;L.n=R.n=0;
for(Re i=1;i<=Po.n;++i){
if(judge(a,Po.P[i],b))R.P[++R.n]=Symmetry_PL(Po.P[i],a,b);//点Po.P[i]在直线ab右边
else if(pan_PL_(Po.P[i],a,b))L.P[++L.n]=R.P[++R.n]=Po.P[i];//点Po.P[i]在直线ab上
else L.P[++L.n]=Po.P[i];//点Po.P[i]在直线ab左边
Re j=i<Po.n?i+1:1;
if(pan_cross_L_L(a,b,Po.P[i],Po.P[j]))L.P[++L.n]=R.P[++R.n]=cross_LL(a,b,Po.P[i],Po.P[j]);//如果直线AB与线段P[i]-P[i+1]有交点,将这个交点入队
while(L.n>1&&L.P[L.n]==L.P[L.n-1])--L.n;//可能会重复如归,这里迅速把它去掉
while(R.n>1&&R.P[R.n]==R.P[R.n-1])--R.n;//同上
}
if(L.n>1&&L.P[1]==L.P[L.n])--L.n;//注意最后判断首尾两点是否重合
if(R.n>1&&R.P[1]==R.P[R.n])--R.n;//同上
if(L.n)Qy[++tt]=L;//如果小矩形不为空就记录下来
if(R.n)Qy[++tt]=R;
}
int main(){
// freopen("123.txt","r",stdin);
scanf("%d",&n);
Py[++t].n=4,Py[t].P[1]=Point(0,0),Py[t].P[2]=Point(0,100),Py[t].P[3]=Point(100,100),Py[t].P[4]=Point(100,0);
//初始化为一个正方形
while(n--){
a.in(),b.in(),tt=0;
for(Re i=1;i<=t;++i)sakura(Py[i],a,b);//切割目前已有的多边形
t=tt;
for(Re i=1;i<=tt;++i)Py[i]=Qy[i];
}
scanf("%d",&T);
while(T--){
a.in();Re ans=0;
for(Re i=1;i<=t;++i)if(PIP(Py[i].P,Py[i].n,a)==1)++ans;//严格在多边形内才统计答案
printf("%d\n",ans);
}
}
【题解】折纸 origami [SCOI2007] [P4468] [Bzoj1074]的更多相关文章
- 【BZOJ】1074: [SCOI2007]折纸origami
http://www.lydsy.com/JudgeOnline/problem.php?id=1074 题意:一开始有一个左上角是(0,100),右下角是(100,0)的纸片,现在可以沿有向直线折n ...
- 1074: [SCOI2007]折纸origami - BZOJ
Description 桌上有一张边界平行于坐标轴的正方形纸片,左下角的坐标为(0,0),右上角的坐标为(100,100).接下来执行n条折纸命令.每条命令用两个不同点P1(x1,y1)和P2(x2, ...
- 1074: [SCOI2007]折纸origami
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 372 Solved: 229[Submit][Status][Discuss] Descriptio ...
- BZOJ1074 [SCOI2007]折纸origami
我们先看每个点可能从哪些点折过来的,2^10枚举对角线是否用到. 然后再模拟折法,查看每个点是否满足要求. 恩,计算几何比较恶心,还好前几天刚写过一道更恶心的计算几何,点类直接拷过来2333. /** ...
- [CSP-S模拟测试]:折纸(模拟)
题目描述 小$s$很喜欢折纸.有一天,他得到了一条很长的纸带,他把它从左向右均匀划分为$N$个单位长度,并且在每份的边界处分别标上数字$0\sim n$.然后小$s$开始无聊的折纸,每次他都会选择一个 ...
- NOIP模拟测试21「折纸·不等式」
折纸 题解 考试时无限接近正解,然而最终也只是接近而已了 考虑模拟会爆炸,拿手折纸条试一试,很简单 考你动手能力 代码 #include<bits/stdc++.h> using name ...
- CSS3写折纸
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
- 折纸问题java实现
/** * 折纸问题 这段代码写的太low了 本人水平有限 哎... 全是字符串了 * @param n * @return * @date 2016-10-7 * @author shaobn */ ...
- CSS3实现文字折纸效果
CSS3实现文字折纸效果 效果图: 代码如下,复制即可使用: <!DOCTYPE html> <html> <head> <title></tit ...
随机推荐
- Check Host:实时监控网站或者服务器是否可以访问
如果你拥有一个网站,那么最重要的事情就是要保证它24小时都能够访问.不过国内的虚拟主机服务非常糟糕,经常会出现各种状况,所以我们需要一个软件,可以让我们第一时间知道网站出现了无法访问的情况,从而通知售 ...
- 微服务下的持续集成-Jenkins自动化部署GitHub项目
@ 目录 一.前言 二.DevOps概念 三.为什么要做持续集成 四.常见云服务 五.手动部署Jenkins 5.1 准备工作 5.2 下载 5.3 启动 5.4 配置 5.5 Jenkins 首页 ...
- Map结合Function函数式接口的巧妙之处
需求:在给定 List 集合中,需根据不同的算法规则,选取计算方式并返回结果: 例如:[1, 2, 3, 4, 5] List 集合中都是 Integer 类型数据,根据提供的算法规则,sum 求和, ...
- 已安装的nginx添加其他模块
总体操作就是添加新模块并重新编译源码,然后把编译后的nginx可执行文件覆盖原来的那个即可.1 查看已安装的参数nginx -V拷贝那些巴拉巴拉的参数,后面编译的时候使用 2 下载相同版本号的源码,解 ...
- 如何使用iMazing编辑iOS设备的备份
乍一看,编辑iPhone或iPad的备份似乎是一个奇怪的命题,但实际上这样做的原因有很多,例如在备份数据损坏时进行修复,又如合并来自不同设备的数据. iMazing对备份文件编辑的支持非常全面,即使备 ...
- Boom 3D的广播有哪些,有啥特色
Boom 3D(Windows系统)不仅为用户提供了包括3D立体音效.古典音乐音效在内的多种音效增强功能,而且还为用户提供了广播功能.该广播功能不仅涵盖了国内广播节目,而且还涵盖了国际广播节目. 接下 ...
- css3系列之详解border-image
border-image border-image呢,是给 边框加上背景图片的.没错,就是平常那一小小条的边框,也能加图片. 参数: border-image-source border-image ...
- 使用axios实现登录功能
1.创建一个login.vue页面 1.1写页面components/Login.vue 在 src/components 下创建 Login.vue 页面 <template> < ...
- python3 Failed to establish a new connection: [WinError 10061] 由于目标计算机积极拒绝,无法连接
报错源代码from selenium import webdriverimport unittestimport timefrom HTMLTestRunner import HTMLTestRunn ...
- Java基础教程——继承
继承 一个类 可以 继承自 另一个类: 派生的类(子类)继承父类的方法和数据成员: 关键字:子类 extends 父类. public class 继承 { public static void ma ...