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. CPP-基础:关于私有成员的访问

    a.C++的类的成员函数中,允许直接访问该类的对象的私有成员变量. b.在类的成员函数中可以访问同类型实例的私有变量. c.拷贝构造函数里,可以直接访问另外一个同类对象(引用)的私有成员. d.类的成 ...

  2. QT+模态对话框与非模态对话框

    #include "mainwindow.h" #include <QMenuBar> #include <QMenu> #include <QAct ...

  3. 第一个WebDriver脚本

    1.cmd下安装selenium,输入pip install selenium 2.下载Firefox浏览器的驱动程序,https://github.com/mozilla/geckodriver/r ...

  4. xcode菜单栏

    File  文件 Edit  编辑 View 视图 Navigate 导航 Editor 编辑 Product 产品 Window  窗口 Help 帮助 File  文件 New 新建        ...

  5. Fortran学习记录1(Fortran数据类型)

    Fortran中的字符 Fortran中的常量 Fortran中的变量 Fortran的I-N规则 Fortran中的有效位数 Fortran中的申明 Fortran中的表达式 Fortran中的语句 ...

  6. Docker安装Oracle12C,导入dmp文件出现ORA-12170错误

    oracle版本为 sath89/oracle-12c oracle基本信息 hostname: localhost port: 1521 sid: xe username: system passw ...

  7. Redis那些事(一) — Redis简介

    本人最近在学习Redis的使用和底层原理,有一些收获,所以希望通过写博客的形式来记录自己的学习过程,加深自己的理解,同时也方便以后查阅复习.目前打算先记录一些基本的使用方法和部分底层实现,其他的如果有 ...

  8. POJ-3624-背包问题

    它这个问题问的是,在有限的容量下,能装下的最大价值是多少. 所以我们可以递归求解,记忆性递归,用二维数组,但是这样的话就会超内存,所以我们只能用动规来写,而且不能开二维数组, 只能用滚动数组. 我们设 ...

  9. layui二次封装

    最近一直用layui进行页面的重构,这个框架十分适合我们后台人员开发.简单易用,但是layui本身不支持双向绑定,所以很多情况下,我们在支持动态的控件加载时,需要反复刷新.这里我自己封装了一个comm ...

  10. Http中cookie的使用以及用CookieManager管理cookie

    前段时间项目需要做个接口,接口需要先登录才能进行下一步操作,这里就需要把登录的信息携带下去,进行下一步操作.网上查了很多资料,有很多种方法.下面就介绍较常用 的. 第一种方式: 通过获取头信息的方式获 ...