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. Mac 查看端口情况

    一个进程可以占用多个端口. 查看某个进程占用哪些端口: lsof -nP | grep TCP | grep -i 进程名 ➜ cocos_creator lsof -nP | grep TCP | ...

  2. 三大框架所使用的UI框架

  3. isEqual ,判断两个对象或变量是否相等

    function isEqual(a, b) { //如果a和b本来就全等 if (a === b) { //判断是否为0和-0 return a !== 0 || 1 / a === 1 / b; ...

  4. GCC、g++编译器和gcc编译器的区别

    GCC:(GNU Compiler Collection,GNU编译器套件),是由 GNU 开发的编程语言编译器.它是以GPL许可证所发行的自由软件,也是 GNU计划的关键部分. gcc:GNU的C语 ...

  5. JavaSE-27 JDBC

    学习要点 JDBC 查询数据 添加数据 修改数据 删除数据 JDBC 1  JDBC的定义 JDBC是Java数据库连接技术的简称,提供连接和操作各种常用数据库的能力. 2  JDBC工作原理 3  ...

  6. MATLAB读取每个文件夹下的badcsv文件后合并为总的badexcel文件

    clear; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%读取子文件夹中bad.csv数据%并把所有数据写到一个excel文件中%%%%%%%%%%%%%%%%%% ...

  7. sqlserver生成脚本

    1.只生成数据 2.只生成架构 3.生成数据和架构

  8. composer 插件安装

    https://packagist.org/?q=phpmyadmin&p=0 Github:笔记 https://github.com/13431/php 类库包下载地址:packagist ...

  9. 3. 对系统表空间使用Raw磁盘分区

    3. 对系统表空间使用Raw磁盘分区 可以将raw磁盘分区用作InnoDB系统表空间中的数据文件.此技术可在Windows和某些Linux和Unix系统上启用非缓冲I/O,而无需文件系统开销.使用和不 ...

  10. 【HIHOCODER 1601】 最大得分(01背包)

    描述 小Hi和小Ho在玩一个游戏.给定一个数组A=[A1, A2, ... AN],小Hi可以指定M个不同的值S1,S2, S3 ... SM,这样他的总得分是 ΣSi × count(Si).(co ...