【题解】切割多边形 [SCOI2003] [P4529] [Bzoj1091]
【题解】切割多边形 [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]的更多相关文章
- poj 2540 Hotter Colder 切割多边形
		
/* poj 2540 Hotter Colder 切割多边形 用两点的中垂线切割多边形,根据冷热来判断要哪一半 然后输出面积 */ #include <stdio.h> #include ...
 - bzoj1091: [SCOI2003]切割多边形
		
Description 有一个凸p边形(p<=8),我们希望通过切割得到它.一开始的时候,你有一个n*m的矩形,即它的四角的坐标分别为(0,0), (0,m), (n,0), (n,m).每次你 ...
 - 【BZOJ】【1091】【SCOI2003】切割多边形
		
计算几何+枚举 我比较傻逼……一开始想了个贪心,就是这样:
 - 题解 P4302 【[SCOI2003]字符串折叠】
		
讲讲我的做法 题目大意:对一个字符串进行折叠是它长度最小 看一眼数据范围:哇!字符串长度不超过100!这是一道省选题,不可能给你太宽裕的时限,所以,题目基本暗示你要用\(n^{3}\)多一些的算法复杂 ...
 - 任意多边形切割/裁剪(附C#代码实现)
		
本实现主要参考了发表于2003年<软件学报>的<一个有效的多边形裁剪算法>(刘勇奎,高云,黄有群)这篇论文,所使用的理论与算法大都基于本文,对论文中部分阐述进行了详细解释,并提 ...
 - BZOJ 1091--切割多边形(几何&枚举)
		
1091: [SCOI2003]切割多边形 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 356 Solved: 157[Submit][Status ...
 - poj3335 半交平面,多边形内核
		
Rotating Scoreboard Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 5300 Accepted: 21 ...
 - TZOJ 2560 Geometric Shapes(判断多边形是否相交)
		
描述 While creating a customer logo, ACM uses graphical utilities to draw a picture that can later be ...
 - WebGIS裁剪算法-线裁剪多边形
		
在gis系统中 经常会用到一些裁剪的方法,首先推荐一个非常好用的空间分析JavaScript库--Turf.js,不仅功能强大.使用简单,同时处理速度也很快. Turf.js中提供了一中多边形的裁剪方 ...
 
随机推荐
- nginx&http 第三章 ngx 请求处理的 11 个阶段 --ngx_http_process_request& ngx_http_handler
			
ngx_http_process_request如果设置了定时器则删除,既然所有的请求已经接收完毕,就不会再发生超时了 重设连接的读写回调函数 重设请求读事件回调函数 调用 ngx_http_hand ...
 - Socket  accept 简要分析
			
accept 用于从指定套接字的连接队列中取出第一个连接,并返回一个新的套接字用于与客户端进行通信,示例代码如下 #include <sys/types.h> /* See NOTES * ...
 - gcc入门(上)
			
gcc:GNU Compiler Collection的缩写.最初是作为C语言的编译器,现在已支持多种语言.Gcc支持多种硬件平台.gcc是一个可移植跨平台编译器gcc还能跨平台交叉编译器.gcc有多 ...
 - Android自定控件基础(一)——几何图形绘制
			
虽然本人有几年开发经验,但是自定义控件这一块儿,研究的很少,惭愧--用到的时候就是百度查找,复制粘贴.工时紧,总是想的快点完工就好.(都是借口啦,想学总会有时间哒) 作为一个Android开发 要说自 ...
 - Ceph根据Crush位置读取数据
			
前言 在ceph研发群里面看到一个cepher在问关于怎么读取ceph的副本的问题,这个功能应该在2012年的时候,我们公司的研发就修改了代码去实现这个功能,只是当时的硬件条件所限,以及本身的稳定性问 ...
 - Linux vi种 wq 、wq!、x、q、q!区别
			
上面的命令只是在vi编辑命令中使用 wq:表示保存退出 wq!:表示强制保存退出 x:表示保存退出 wq和wq!的区别如下: 有些文件设置了只读,一般不是修改文件的,但是如果你是文件的owner或者r ...
 - 使用Actor模型管理Web Worker多线程
			
前端固有的编程思维是单线程,比如JavaScript语言的单线程.浏览器JS线程与UI线程互斥等等,Web Woker是HTML5新增的能力,为前端带来多线程能力.这篇文章简单记录一下搜狗地图WebG ...
 - 不会吧,你连Java 多线程线程安全都还没搞明白,难怪你面试总不过
			
什么是线程安全? 当一个线程在同一时刻共享同一个全局变量或静态变量时,可能会受到其他线程的干扰,导致数据有问题,这种现象就叫线程安全问题. 为什么有线程安全问题? 当多个线程同时共享,同一个全局变量或 ...
 - python定时执行详解
			
知识点 1. sched模块,准确的说,它是一个调度(延时处理机制),每次想要定时执行某任务都必须写入一个调度. (1)生成调度器:s = sched.scheduler(time.time,time ...
 - Jmeter测试TCP协议
			
最近做了个项目是TCP协议传输数据,于是马上想试试JMeter测试TCP. 1首先需要下载第三方的TCP插件包ApacheJMeter_tcp.jar,下载步骤请自行百度. 2.下载完重新配置jmet ...