【题解】切割多边形 [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中提供了一中多边形的裁剪方 ...
随机推荐
- #paragma详解
#Pragma是预处理指令,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#Pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统 ...
- 《GNU_makefile》第七章——makefile的条件执行
条件执行即,通过变量的值,来控制make的执行和忽略. 条件执行只能控制makefile的make语法部分,不能控制shell部分 1.一个例子 - libs_for_gcc = -lgnu norm ...
- Elasticsearch 第八篇:数据类型 Array、Nested、Object 的设计与应用
h2.post_title { background-color: rgba(43, 102, 149, 1); color: rgba(255, 255, 255, 1); font-size: 1 ...
- Vue 组件化开发
组件化开发 基本概念 在最开始的时候,已经大概的聊了聊Vue是单页面开发,用户总是在一个页面上进行操作,看到的不同内容也是由不同组件构成的. 通过用户的操作,Vue将会向用户展示某些组件,也会隐藏某些 ...
- SQL Server 常用近百条SQL语句(收藏版)
1. sqlserver查看实例级别的信息,使用SERVERPROPERTY函数 select SERVERPROPERTY ('propertyname') 2. 查看实例级别的某个参数XX的配置 ...
- 通过一道CTF学习HTTP协议请求走私
HTTP请求走私 HTTP请求走私 HTTP请求走私是针对于服务端处理一个或者多个接收http请求序列的方式,进行绕过安全机制,实施未授权访问一种攻击手段,获取敏感信息,并直接危害其他用户. 请求走私 ...
- vue路由参数的获取、添加和替换
获取路由参数 getUrlKey(name){//获取url 参数 return decodeURIComponent((new RegExp('[?|&]'+name+'='+'([^&am ...
- 还不懂spring中的bean的话,你一定得好好看看这篇文章
bean的作用域 bean的生命周期 bean的装配 代码 实体类 package com; import java.util.List; public class User { private St ...
- 面试半年,凭借这份JVM面试题,我终于拿到了字节跳动的offer!
内存区域 虚拟机栈生命周期与线程相同,描述的是Java 方法执行的内存模型,每个方法在执行的时候都会创建一个栈帧,用于存取局部变量表.操作数栈.动态链接.方法出口等信息本地方法栈与虚拟机栈作用相似,只 ...
- jenkins、gitlab配置CI/CD
1. 在gitlab中创建好项目(gitlab的安装和基本使用这里不在说明) 2. 创建jenkins任务 jenkins 需要几个插件请先安装好 - Git plugin - GitLab Plug ...