【题解】切割多边形 [SCOI2003] [P4529] [Bzoj1091]

传送门:切割多边形 \(\text{[SCOI2003] [P4529]}\) \(\text{[Bzoj1091]}\)

【题目描述】

给出一个 \(Mx*My\) \((0 < Mx,My < 500)\) 的矩形,现要用 \(n\) \((3 \leqslant n \leqslant 8)\) 条直线依次对其进行切割,将它变成凸 \(n\) 边形,每次切割的长度为该直线在剩下的矩形内部的部分的长度,求最短的切割线总长度。

【分析】

一道计算几何膜您题。

由于 \(n\) 比较小,可以 \(O(n!)\) 枚举切割线的顺序,最后计算总长度取最小值就行了。

但有个非常麻烦的问题:如何求每次加入直线的切割线长度?

考虑用一个栈储存当前已经加入的直线(上下左右四个边界会在最初时加入),如果现在要加入直线 \(p_1-p_2\)(这里为方便描述,设 \(p_1\) 在左边,\(p_2\) 在右边),先求出它与栈中所有直线的交点,然后在这些交点中分别找到:\(p_1\) 左边距离 \(p_1\) 最近的点 \(ans_1\) 和 \(p_2\) 右边距离 \(p_2\) 最近的点\(ans_2\),易知 \(len(ans_1,ans_2)\) 即为当次切割线长度。

图就不画了,自己领会吧。。。

【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=20;
const LD eps=1e-9,inf=1e9;
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);}
}p1,p2,p3,p4,P[N];
struct Line{
Point a,b;int id;LD k;Line(Point X=Point(0,0),Point Y=Point(0,0),int ID=0,LD K=0){a=X,b=Y,id=ID,k=K;}
inline void sakura(){k=(!dcmp(a.x-b.x))?0.0:(a.y-b.y)/(a.x-b.x);}
inline bool operator<(Line O)const{return k<O.k;}
}L[N],Q[N];
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 Point operator+(Point a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
inline Vector operator-(Point a,Point 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 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
}
int n,t,a[N],vis[N];LD Mx,My,Ans=inf;
inline void dfs(Re g,LD ans){
if(g>n){Ans=min(Ans,ans);return;}
for(Re i=1;i<=n;++i)
if(!vis[i]){
Point p1=L[i].a,p2=L[i].b,ans1=Point(inf,inf),ans2=Point(inf,inf);
//ans1:在p2-p1延长线上距离p1最近的点
//ans2:在p1-p2延长线上距离p2最近的点
for(Re j=1;j<=t;++j){
Point b=cross_LL(p1,p2,Q[j].a,Q[j].b);//获取直线L[i]与Q[i]的交点b
if(dcmp(Len(p1-b)-Len(p2-b))<0&&dcmp(Len(p1-ans1)-Len(p1-b))>0)ans1=b;//如果 len(b,p1)<len(b,p2) 且 len(p1,b)<len(p1,ans1)
if(dcmp(Len(p2-b)-Len(p1-b))<0&&dcmp(Len(p2-ans2)-Len(p2-b))>0)ans2=b;//如果 len(b,p2)<len(b,p1) 且 len(p2,b)<len(p2,ans2)
}
vis[i]=1,Q[++t]=L[i];
dfs(g+1,ans+Len(ans1-ans2));//加上len(ans1,ans2)
vis[i]=0,--t;
}
}
int main(){
// freopen("123.txt","r",stdin);
scanf("%lf%lf%d",&Mx,&My,&n);
for(Re i=1;i<=n;++i)P[i].in();
for(Re i=1;i<=n;++i)L[i]=Line(P[i],P[i<n?i+1:1],i);//获取n条直线
p1=Point(0,0),p2=Point(0,My),p3=Point(Mx,My),p4=Point(Mx,0);//四个顶点
Q[++t]=Line(p1,p2),Q[++t]=Line(p2,p3),Q[++t]=Line(p3,p4),Q[++t]=Line(p4,p1);//先将四个边界入队
dfs(1,0.0);
printf("%.3lf\n",Ans);
}

【题解】切割多边形 [SCOI2003] [P4529] [Bzoj1091]的更多相关文章

  1. poj 2540 Hotter Colder 切割多边形

    /* poj 2540 Hotter Colder 切割多边形 用两点的中垂线切割多边形,根据冷热来判断要哪一半 然后输出面积 */ #include <stdio.h> #include ...

  2. bzoj1091: [SCOI2003]切割多边形

    Description 有一个凸p边形(p<=8),我们希望通过切割得到它.一开始的时候,你有一个n*m的矩形,即它的四角的坐标分别为(0,0), (0,m), (n,0), (n,m).每次你 ...

  3. 【BZOJ】【1091】【SCOI2003】切割多边形

    计算几何+枚举 我比较傻逼……一开始想了个贪心,就是这样:

  4. 题解 P4302 【[SCOI2003]字符串折叠】

    讲讲我的做法 题目大意:对一个字符串进行折叠是它长度最小 看一眼数据范围:哇!字符串长度不超过100!这是一道省选题,不可能给你太宽裕的时限,所以,题目基本暗示你要用\(n^{3}\)多一些的算法复杂 ...

  5. 任意多边形切割/裁剪(附C#代码实现)

    本实现主要参考了发表于2003年<软件学报>的<一个有效的多边形裁剪算法>(刘勇奎,高云,黄有群)这篇论文,所使用的理论与算法大都基于本文,对论文中部分阐述进行了详细解释,并提 ...

  6. BZOJ 1091--切割多边形(几何&枚举)

    1091: [SCOI2003]切割多边形 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 356  Solved: 157[Submit][Status ...

  7. poj3335 半交平面,多边形内核

    Rotating Scoreboard Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5300   Accepted: 21 ...

  8. TZOJ 2560 Geometric Shapes(判断多边形是否相交)

    描述 While creating a customer logo, ACM uses graphical utilities to draw a picture that can later be ...

  9. WebGIS裁剪算法-线裁剪多边形

    在gis系统中 经常会用到一些裁剪的方法,首先推荐一个非常好用的空间分析JavaScript库--Turf.js,不仅功能强大.使用简单,同时处理速度也很快. Turf.js中提供了一中多边形的裁剪方 ...

随机推荐

  1. tcp输入数据 慢速路径处理 && oob数据 接收 && 数据接收 tcp_data_queue

    大致的处理过程 TCP的接收流程:在tcp_v4_do_rcv中的相关处理(网卡收到报文触发)中,会首先通过tcp_check_urg设置tcp_sock的urg_data为TCP_URG_NOTYE ...

  2. 手写一个最迷你的Web服务器

    今天我们就仿照Tomcat服务器来手写一个最简单最迷你版的web服务器,仅供学习交流. 1. 在你windows系统盘的F盘下,创建一个文件夹webroot,用来存放前端代码.  2. 代码介绍: ( ...

  3. Adaboost算法的一个简单实现——基于《统计学习方法(李航)》第八章

    最近阅读了李航的<统计学习方法(第二版)>,对AdaBoost算法进行了学习. 在第八章的8.1.3小节中,举了一个具体的算法计算实例.美中不足的是书上只给出了数值解,这里用代码将它实现一 ...

  4. 记最近一次ceph故障修复

    前言 所谓吃一堑长一智,每次面对问题才是最好的学习机会,在面对问题的时候,尽量是能够自己去解决,或者去尝试能够最接近答案,确实无法解决再去寻求他人帮助,这样成长的会更快一些,在学校读书做题的时候,老师 ...

  5. Docker版EKL安装记录文档

    Docker版EKL安装记录文档 拉取已下三个镜像 docker.io/logstash 7.5.2 b6518c95ed2f 6 months ago 805 MB docker.io/kibana ...

  6. 「LOJ 537」「LibreOJ NOIP Round #1」DNA 序列

    description NOIP 复赛之前,HSD 桑进行了一项研究,发现人某条染色体上的一段 DNA 序列中连续的\(k\)个碱基组成的碱基序列与做题的 AC 率有关!于是他想研究一下这种关系. 现 ...

  7. python3安装mysqlclient,解决django使用pymysql报错的问题

    1.起因 在django中为了使用MySQL,一般是在项目目录下的__init__.py中添加 import pymysql pymysql.install_as_MySQLdb() # 使用pymy ...

  8. Session 与 sql 会话,mysql 权限设置,mybatis 逆向工程

    Session 与 Sql 会话注意点: 通过 sqlSessionFactoty 工厂建立的与sql的会话,在进行相应的插入操作后,需要进行 commit 操作才会让数据库执行插入更新操作.如何主键 ...

  9. JQuery案例:左右选

    左右选 <head> <meta charset="UTF-8"> <title></title> <style> se ...

  10. 给你的C/C++学习路线建议

    因为程序员的高工资,吸引了大部人学习编程,但是通过书籍和视频来学习,总是别人推荐一点是一点,那么如何才能系统有效的学习呢?今天就为你来介绍~ C语言是所有学习编程的人都应该首要学习的语言,今天就C语言 ...