1091: [SCOI2003]切割多边形

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 356  Solved: 157
[Submit][Status][Discuss]

Description

  有一个凸p边形(p<=8),我们希望通过切割得到它。一开始的时候,你有一个n*m的矩形,即它的四角的坐标分别为(0,0), (0,m), (n,0), (n,m)。每次你可以选择一条直线把当前图形切割成两部分,保留其中一个部分(另一部分扔掉)切割线的长度为此直线在多边形内部的部分的长度。求出最短的切割线总长度。下面是一个例子。

  分别沿着直线1,2,3,4进行切割即可,得到中间的四边形。

Input

  第一行有两个整数n, m(0 < n,m < 500),第二行为一个整数p(3<=p<=8)。以下p行每行为两个整数x, y(0 < x< n, 0 < y < m),为按顺时针给出的各顶点坐标。数据保证多边形的是凸的,无三点共线。输入数据无错误。

Output

  仅一行,为最短切割线的总长度,四舍五入到小数点后3位。允许有0.001的误差。

Sample Input

100 100
4
80 80
70 30
20 20
20 80

Sample Output

312.575

HINT

样例对应于图中给出的例子。

题目链接:

    http://www.lydsy.com/JudgeOnline/problem.php?id=1091

Solution

    心态都打崩了。。。调了一个多小时。。。。

    感觉思路和网上其他题解很像啊。。。为什么代码量差这么多。。。

    我打了5k+字的代码呀。。。。然而别人只用不到2k字就过了。。。。。。。

    我的思路是枚举切割顺序,然后强行计算答案。。。。

    因为边数小于8,所以最多只有8!个答案。。。

    至于答案的计算方法。。。。

    我是先计算出每两条边的交点,显然平行边是没有交点的于是特判掉。。。

    然后枚举切割顺序,计算每条边的最小切割长度。。。

    于是就会有一个问题:每一次的交点会在当前线段的那一端?

    根据直线函数 y = k * x + b ,说明 x + y 的值一定是有单调性的,于是比较一下当前点和线段两端点的横纵坐标和即可。。。

    但这个定理有个反例: 当 k = -1 的时候 x + y 的值是不变的,这个特例也要特判。。。。

    然后就可以了。。。。感觉似乎网上有简单的多的方法。。。心态已崩。。。。。。。。。

    请允许我贴上我那又长又臭的代码。。。。。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
inline int Read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,p;
double ans,inf;
int q[10];
bool vis[10];
struct dt{
double x,y;
}d[10],D[5],mp[10][10],MP[10][5];
struct edge{
double son1x,son1y;
double son2x,son2y;
int ty1,ty2;
double k,b,s;
}e[10],E[5];
void calc_edge(edge &t){
t.ty1=t.ty2=0;
t.s=t.son1x+t.son1y+t.son2x+t.son2y;
if(t.son1x+t.son1y>t.son2x+t.son2y){
swap(t.son1x,t.son2x);
swap(t.son1y,t.son2y);
}
if(t.son1y==t.son2y) t.ty1=1;
else if(t.son1x==t.son2x) t.ty2=1;
else{
t.k=(double)(t.son1y-t.son2y)/(double)(t.son1x-t.son2x);
t.b=(double)t.son1y-(double)t.son1x*t.k;
}
}
dt calc_dt(edge A,edge B){
dt re;
if(A.ty1){
if(B.ty1){re.x=re.y=inf;return re;}
re.y=A.son1y;
if(B.ty2){re.x=B.son1x;return re;}
re.x=(re.y-B.b)/B.k;
return re;
}
if(A.ty2){
if(B.ty2){re.x=re.y=inf;return re;}
re.x=A.son1x;
if(B.ty1){re.y=B.son1y;return re;}
re.y=re.x*B.k+B.b;
return re;
}
if(B.ty1){re.y=B.son1y;re.x=(re.y-A.b)/A.k;return re;}
if(B.ty2){re.x=B.son1x;re.y=re.x*A.k+A.b;return re;}
if(B.k==A.k){re.x=re.y=inf;return re;}
re.x=(B.b-A.b)/(A.k-B.k);re.y=re.x*A.k+A.b;return re;
}
double len(double x1,double y1,double x2,double y2){
return (double)sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
void CALC(){
double Ans=0;
dt L,R,now;
for(int i=1;i<=p;i++){
L.x=L.y=R.x=R.y=inf;
if(e[q[i]].ty1 || e[q[i]].ty2 || (e[q[i]].k!=-1)){
for(int j=1;j<=4;j++){
now=MP[q[i]][j];
if(now.x==inf && now.y==inf)continue;
if((double)2*(now.x+now.y)>(double)e[q[i]].s){
if(R.x==inf && R.y==inf) R=now;
else if(len(R.x,R.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))R=now;
}
else{
if(L.x==inf && L.y==inf) L=now;
else if(len(L.x,L.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))L=now;
}
}
for(int j=1;j<i;j++){
now=mp[q[i]][q[j]];
if(now.x==inf && now.y==inf)continue;
if((double)2*(now.x+now.y)>(double)e[q[i]].s){
if(R.x==inf && R.y==inf) R=now;
else if(len(R.x,R.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))R=now;
}
else{
if(L.x==inf && L.y==inf) L=now;
else if(len(L.x,L.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))L=now;
}
}
}
else{
for(int j=1;j<=4;j++){
now=MP[q[i]][j];
if(now.x==inf && now.y==inf)continue;
if((double)2*now.x>(double)e[q[i]].son1x+e[q[i]].son2x){
if(R.x==inf && R.y==inf) R=now;
else if(len(R.x,R.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))R=now;
}
else{
if(L.x==inf && L.y==inf) L=now;
else if(len(L.x,L.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))L=now;
}
}
for(int j=1;j<i;j++){
now=mp[q[i]][q[j]];
if(now.x==inf && now.y==inf)continue;
if((double)2*now.x>(double)e[q[i]].son1x+e[q[i]].son2x){
if(R.x==inf && R.y==inf) R=now;
else if(len(R.x,R.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))R=now;
}
else{
if(L.x==inf && L.y==inf) L=now;
else if(len(L.x,L.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))L=now;
}
}
}
Ans=Ans+len(L.x,L.y,R.x,R.y);
}
if(Ans<ans) ans=Ans;
}
void dfs(int cs){
if(cs>p){CALC();return;}
for(int i=1;i<=p;i++){
if(vis[i])continue;
vis[i]=1;
q[cs]=i;
dfs(cs+1);
vis[i]=0;
}
return;
}
int main(){
inf=10000000000.0;
ans=inf;
n=Read();m=Read();p=Read();
D[1].x=(double)0;D[1].y=(double)0;D[2].x=(double)0;D[2].y=(double)m;
D[3].x=(double)n;D[3].y=(double)m;D[4].x=(double)n;D[4].y=(double)0;
for(int i=1;i<4;i++){
E[i].son1x=D[i].x;E[i].son1y=D[i].y;
E[i].son2x=D[i+1].x;E[i].son2y=D[i+1].y;
}
E[4].son1x=D[4].x;E[4].son1y=D[4].y;
E[4].son2x=D[1].x;E[4].son2y=D[1].y;
for(int i=1;i<=4;i++) calc_edge(E[i]);
for(int i=1;i<=p;i++){
d[i].x=(double)Read();d[i].y=(double)Read();
}
for(int i=1;i<p;i++){
e[i].son1x=d[i].x;e[i].son1y=d[i].y;
e[i].son2x=d[i+1].x;e[i].son2y=d[i+1].y;
}
e[p].son1x=d[p].x;e[p].son1y=d[p].y;
e[p].son2x=d[1].x;e[p].son2y=d[1].y;
for(int i=1;i<=p;i++) calc_edge(e[i]);
for(int i=1;i<=p;i++)
for(int j=1;j<=p;j++)
if(i!=j) mp[j][i]=mp[i][j]=calc_dt(e[i],e[j]);
for(int i=1;i<=p;i++)
for(int j=1;j<=4;j++)
MP[i][j]=calc_dt(e[i],E[j]);
dfs(1);
printf("%0.3lf\n",ans);
return 0;
}

  

  

This passage is made by Iscream-2001.

BZOJ 1091--切割多边形(几何&枚举)的更多相关文章

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

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

  2. poj 2540 Hotter Colder 切割多边形

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

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

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

  4. BZOJ 1091([SCOI2003]分割多边形-分割直线)

    1091: [SCOI2003]分割多边形 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 223  Solved: 82 [Submit][id=10 ...

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

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

  6. [BZOJ 1028] [JSOI2007] 麻将 【枚举+贪心判断】

    题目链接:BZOJ - 1028 题目分析 枚举听的是哪种牌,再枚举成对的是哪种牌,再贪心判断: 从1到n枚举每一种牌,如果这种牌的个数小于0,就返回不合法. 将这种牌的张数 % 3, 剩下的只能和 ...

  7. BZOJ 3901 棋盘游戏 (找结论+枚举+贪心)

    题面 略 BZOJ 传送门 分析 具体分析见 dalao博客 妙就妙在当i<x,j<xi<x,j<xi<x,j<x时,(i,j)(i,j)(i,j) ^ (i,x) ...

  8. hdu1115(计算多边形几何重心)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1115 题意:给出一些点,求这些点围成的多边形的重心: 思路: 方法1:直接分别求所有点的x坐标的平均值 ...

  9. [BZOJ 2241][SDOI2011]打地鼠(枚举+预处理)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2241 分析: 鉴于R,C的取值很小,于是可以人为枚举R和C的大小,然后判定这个规格的锤 ...

随机推荐

  1. 7.25 10figting!

    TEXT 88 European utilities欧洲公用事业 Power struggles 能源之争(陈继龙编译) Nov 30th 2006 From The Economist print ...

  2. sdm 使用阿里云域名申请 Let’s Encrypt 通配符 域名证书

    安装acme 进入 套件中心 点击安装 Git Server 之后进入SSh会使用git命令 方法1--------------------------------------- 获取代码 git c ...

  3. ArcGIS GP服务的发布及调用

    参考https://www.jianshu.com/p/5331fa708fe5

  4. Visual Studio 2017 无法打开包括文件: “QOpenGLWidget”: No such file or directory

    编译项目时,发现报错:VS 无法打开包括文件: “QOpenGLWidget”: No such file or directory,在Qt对应的目录(E:\Qt\Qt5.12.2\5.12.2\ms ...

  5. React Native 常用插件案例

    (二).基础入门: 1.React Native For Android环境配置以及第一个实例 2.React Native开发IDE安装及配置 3.React Native应用设备运行(Runnin ...

  6. How to setup Laravel Homestead in Windows

    How to setup Laravel Homestead in Windows by JBorbón  17. March 2017   PHP   8 Developing with PHP u ...

  7. 如何使用vsphere client 克隆虚拟机

    vSphere 是VMware公司推出一套服务器虚拟化解决方案. 工具/原料 vSphere 测试系统 方法/步骤 1.进入vSphere client,关闭需要克隆的虚拟机win7 2.选中ESXi ...

  8. C#的链表操作[数据结构-线性表]

    链式存储结构图解: 上图中,a1,是数据,紧跟着后面的d1是下一个节点的地址值.也就是一个节点的最后存储的是下一个节点的地址值,最后一个节点的存储的下一个地址值是null,代表链表结束. 1,定义链表 ...

  9. java通过经纬度计算两个点的之间的距离的算法

    通过两个点的经纬度计算距离 从google maps的脚本里扒了段代码,没准啥时会用上.大家一块看看是怎么算的. private const double EARTH_RADIUS = 6378.13 ...

  10. 【转载】【JAVA秒会技术之图片上传】基于Nginx及FastDFS,完成图片的上传及展示

    基于Nginx及FastDFS,完成商品图片的上传及展示 一.传统图片存储及展示方式 存在问题: 1)大并发量上传访问图片时,需要对web应用做负载均衡,但是会存在图片共享问题 2)web应用服务器的 ...