1091: [SCOI2003]分割多边形

Time Limit: 1 Sec  Memory Limit: 162 MB

Submit: 223  Solved: 82

[Submit][

id=1091" style="color:blue; text-decoration:none">Status]

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

例子相应于图中给出的例子。

Source

直接把多边形伸长成2点都在矩形上的线段,这种话每次取时把之前的线段割一下。

注意伸长时保证向量方向

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define MP make_pair
#define MAXP (500+10)
#define MAXN (500+10)
#define MAXM (500+10)
#define eps (1e-6)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
int n,m,p;
double sqr(double x){return x*x;}
int dcmp(double a,double b=0){if (fabs(a-b)<=eps) return 0;else if (a<b) return -1;return 1;}
struct P
{
double x,y;
P(){}
P(double _x,double _y):x(_x),y(_y){}
friend istream& operator>>(istream& cin,P &a){cin>>a.x>>a.y;return cin;}
friend ostream& operator<<(ostream& cout,P &a){cout<<a.x<<' '<<a.y;return cout;}
friend bool operator==(P a,P b){return dcmp(a.x,b.x)==0&&dcmp(a.y,b.y)==0; }
}a[MAXP];
struct V
{
double x,y;
V(){}
V(double _x,double _y):x(_x),y(_y){}
V(P a,P b):x(b.x-a.x),y(b.y-a.y){}
friend V operator*(double a,V b){return V(a*b.x,a*b.y);}
friend V operator-(P a,P b){return V(b.x-a.x,b.y-a.y); }
friend double operator*(V a,V b){return a.x*b.y-a.y*b.x;}
friend double operator^(V a,V b){return a.x*b.x+a.y*b.y;}
friend P operator+(P a,V b){return P(a.x+b.x,a.y+b.y); }
friend double dis2(V a){return sqr(a.x)+sqr(a.y); }
};
struct L
{
P p;
V v;
L(){}
L(P _A,V _B):p(_A),v(_B){}
friend bool parallel(L a,L b) {return (dcmp(a.v.x*b.v.y,a.v.y*b.v.x))==0;}
friend P intersect(L a,L b) //直线交点
{
V &v=a.v,&w=b.v,u=V(b.p,a.p);
double t=(w*u)/(v*w);
P c=a.p+t*v; return c;
}
friend bool inleft(P a,L b){return dcmp(b.v*V(b.p,a))>=0; }
void print(){cout<<p.x<<' '<<p.y<<' '<<v.x<<' '<<v.y<<endl; }
}l[MAXP],lrec[4];
bool inrec(P a){return (dcmp(a.x)>=0&&dcmp(a.x,n)<=0&&dcmp(a.y)>=0&&dcmp(a.y,m)<=0);}
L through_rec_line(L l)
{
int siz=0;P st[3];
if (dcmp(l.v.x)==0) return L(P(l.p.x,l.v.y>0?0:m),V(0,(l.v.y>0?1:-1)*m));
if (dcmp(l.v.y)==0) return L(P(l.v.x>0?0:n,l.p.y),V((l.v.x>0?1:-1)*n,0)); //至此保证不平行坐标系
Rep(i,4)
{
if (parallel(lrec[i],l)) continue;
st[++siz]=intersect(lrec[i],l);
if (!inrec(st[siz])) siz--;
if (siz==2)
{
if (st[1]==st[2]) siz--;
else
{
V a=V(st[1],st[2]);
if (dcmp(a^l.v)<0) return L(st[2],V(st[2],st[1]));
return L(st[1],a);
}
}
}
}
bool b[MAXP]={0};
double ans=1e300;
int cut_list[MAXN];
void dfs(double tot,int siz)
{
if (tot>ans) return;
if (siz==p)
{
// Rep(i,siz) cout<<cut_list[i]<<' ';printf("%.3lf\n",ans);
ans=min(ans,tot);
return;
} /*
if (siz==2)
{
if (cut_list[0]==2&&cut_list[1]==1)
{
cout<<' ';
}
}*/ For(i,p)
if (!b[i])
{
L x=through_rec_line(l[i]);
For(j,p)
if (!parallel(l[j],x)&&b[j])
{
P p=intersect(x,l[j]);
if (dcmp(V(p,x.p)^V(p,x.p+x.v))<0)
{
if (!inleft(x.p,l[j])) x=L(p,V(p,x.p+x.v));
else if (!inleft(x.p+x.v,l[j])) x=L(x.p,V(x.p,p));
}
}
b[i]=1;
cut_list[siz]=i;
/*
Rep(j,siz) printf("\t");
cout<<i<<endl;
printf("%.3lf\n",tot+sqrt(dis2(x.v)));
*/
dfs(tot+sqrt(dis2(x.v)),siz+1);
b[i]=0;
}
}
int main()
{
// freopen("bzoj1091.in","r",stdin);
// freopen("bzoj1091.out","w",stdout); cin>>n>>m>>p;
ForD(i,p) cin>>a[i];memcpy(a+p+1,a+1,sizeof(P)*p);
For(i,p) l[i]=L(a[i],V(a[i],a[i+1]));memcpy(l+p+1,l+1,sizeof(L)*p); lrec[0]=L(P(0,0),V(n,0)),lrec[1]=L(P(n,0),V(0,m)),lrec[2]=L(P(n,m),V(-n,0)),lrec[3]=L(P(0,m),V(0,-m));
For(i,p) l[i]=through_rec_line(l[i]); // For(i,p) l[i].print(); dfs(0,0); printf("%.3lf\n",ans);
return 0;
}

BZOJ 1091([SCOI2003]分割多边形-分割直线)的更多相关文章

  1. leaflet结合turf.js实现多边形分割(附源码下载)

    前言 leaflet 入门开发系列环境知识点了解: leaflet api文档介绍,详细介绍 leaflet 每个类的函数以及属性等等 leaflet 在线例子 leaflet 插件,leaflet ...

  2. C 语言 字符串命令 strstr()的用法 实现将原字符串以分割串分割输出

    C 语言 字符串命令 strstr()的用法 实现将原字符串以分割串分割输出 strstr() 命令是在原字符串中查找指定的字符串第一次出现的地址,用这个特性可以实现字符的分割,判断是否包涵等功能: ...

  3. 【BZOJ】3675: [Apio2014]序列分割

    http://www.lydsy.com/JudgeOnline/problem.php?id=3675 题意:给一个n个数字的序列,每一次分割的贡献是$sum(left, mid)*sum(mid+ ...

  4. 【BZOJ】1044: [HAOI2008]木棍分割 二分+区间DP

    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1044 Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, ...

  5. 【BZOJ】1044: [HAOI2008]木棍分割(二分+dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1044 如果只求最大的最小,,直接二分就行了...可是要求方案.. 好神! 我竟然想不到! 因为我们得 ...

  6. BZOJ:5092 [Lydsy1711月赛]分割序列(贪心&高维前缀和)

    Description 对于一个长度为n的非负整数序列b_1,b_2,...,b_n,定义这个序列的能量为:f(b)=max{i=0,1,...,n}((b_1 xor b _2 xor...xor ...

  7. bzoj 3559: [Ctsc2014]图的分割【最小生成树+并查集】

    读题两小时系列-- 在读懂题意之后,发现M(c)就是c这块最大权割边也就是的最小生成树的最大权边的权值,所以整个问题都可以在MST的过程中解决(M和c都是跟着并查集变的) 不过不是真的最小生成树,是合 ...

  8. 【BZOJ 3675】[Apio2014]序列分割

    [链接] 链接 [题意] 在这里输入题意 [题解] 模拟一下样例. 会发现.切的顺序不影响最后的答案. 只要切点确定了. 答案就确定了. 则设f[i][j]表示前i段,第i段保留到j的最大值. \(f ...

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

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

随机推荐

  1. encodeURI()与decodeURI()等转码方法

    只针对文本编码 encodeURI() 只针对文本解码 decodeURI()针对文本和特殊字符的编码  encodeURIComponent()针对文本和特殊字符的解码  decodeURIComp ...

  2. JDK的4种引用类型

    在java中,大致有以下几种引用类型,强引用(StrongReference).软引用(SoftReference).弱引用(WeakReference).虚引用(PhantomReference) ...

  3. dotTrace激活服务器

    http://active.09l.me IntelliJ IDEA 7.0 或 更高DataGrip 1.0或更高ReSharper 3.1 或更高ReSharper Cpp 1.0 或更高dotT ...

  4. 【开发工具安装配置】MyEclipse,Tomcat,Mysql安装配置

    配置步骤 注:以下路径仅供参考! 一.MyEclipse10 1. 1 破解版破解说明: (1)下载安装好Myeclipse,先不要运行. (2)打开破解工具目录下的cracker.jar文件或run ...

  5. 树莓派 - MQTT

    安装mosquitto 下载源代码包 wget http://mosquitto.org/files/source/mosquitto-1.5.tar.gz 解压 tar zxfv mosquitto ...

  6. maven打包oracle jdbc驱动

    背景 由于版权问题,maven中央仓库缺少oracle jdbc的驱动,这个给开发带来了很多不便利性.也出现各种各样的解决方案,基本就两种思路: 将oracle驱动安装到本地仓库,这个需要大家统一好名 ...

  7. 嵩天老师的零基础Python笔记:https://www.bilibili.com/video/av15123607/?from=search&seid=10211084839195730432#page=25 中的42-45讲 {字典}

    #coding=gbk#嵩天老师的零基础Python笔记:https://www.bilibili.com/video/av15123607/?from=search&seid=1021108 ...

  8. Selenium学习系列---- FirePath的安装和使用

    在用Selenium编写测试用例的时候,需要对对网页元素上定位,而现在很多的浏览器是可以看到网页上相关的元素信息,可以查看某一个网页的元素信息,通过定位的方式查找元素.另外安装好Selenium ID ...

  9. Leetcode 297.二叉树的序列化和反序列化

    二叉树地序列化和反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据. ...

  10. NYOJ90-整数划分,经典递归思想~~

    整数划分 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 将正整数n表示成一系列正整数之和:n=n1+n2+-+nk,  其中n1≥n2≥-≥nk≥1,k≥1.  正整数 ...