BZOJ 1091--切割多边形(几何&枚举)
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
4
80 80
70 30
20 20
20 80
Sample Output
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--切割多边形(几何&枚举)的更多相关文章
- 【题解】切割多边形 [SCOI2003] [P4529] [Bzoj1091]
[题解]切割多边形 [SCOI2003] [P4529] [Bzoj1091] 传送门:切割多边形 \(\text{[SCOI2003] [P4529]}\) \(\text{[Bzoj1091]}\ ...
- poj 2540 Hotter Colder 切割多边形
/* poj 2540 Hotter Colder 切割多边形 用两点的中垂线切割多边形,根据冷热来判断要哪一半 然后输出面积 */ #include <stdio.h> #include ...
- 【BZOJ】【1091】【SCOI2003】切割多边形
计算几何+枚举 我比较傻逼……一开始想了个贪心,就是这样:
- BZOJ 1091([SCOI2003]分割多边形-分割直线)
1091: [SCOI2003]分割多边形 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 223 Solved: 82 [Submit][id=10 ...
- bzoj1091: [SCOI2003]切割多边形
Description 有一个凸p边形(p<=8),我们希望通过切割得到它.一开始的时候,你有一个n*m的矩形,即它的四角的坐标分别为(0,0), (0,m), (n,0), (n,m).每次你 ...
- [BZOJ 1028] [JSOI2007] 麻将 【枚举+贪心判断】
题目链接:BZOJ - 1028 题目分析 枚举听的是哪种牌,再枚举成对的是哪种牌,再贪心判断: 从1到n枚举每一种牌,如果这种牌的个数小于0,就返回不合法. 将这种牌的张数 % 3, 剩下的只能和 ...
- BZOJ 3901 棋盘游戏 (找结论+枚举+贪心)
题面 略 BZOJ 传送门 分析 具体分析见 dalao博客 妙就妙在当i<x,j<xi<x,j<xi<x,j<x时,(i,j)(i,j)(i,j) ^ (i,x) ...
- hdu1115(计算多边形几何重心)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1115 题意:给出一些点,求这些点围成的多边形的重心: 思路: 方法1:直接分别求所有点的x坐标的平均值 ...
- [BZOJ 2241][SDOI2011]打地鼠(枚举+预处理)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2241 分析: 鉴于R,C的取值很小,于是可以人为枚举R和C的大小,然后判定这个规格的锤 ...
随机推荐
- Dirichlet Process
http://www.cnblogs.com/zhangbojiangfeng/p/5962039.html [各种函数推导]
- Kubuntu中thunderbird最小化到任务栏
作为邮件客户端,如果没有办法显示在任务栏中,实在是说不过去.遗憾的是thunderbird默认真不带这个功能(因为Linux的桌面系统太混乱了?)... 当然,解决也十分简单,只要安装Firetray ...
- 286 walls and gate最近的出口
[抄题]: 您将获得一个使用这三个可能值初始化的 m×n 2D 网格.-1 - 墙壁或障碍物. 0 - 门. INF - Infinity是一个空房间.我们使用值 2 ^ 31 - 1 = 21474 ...
- 如果使用mybatis的逆向工程生成的po类及mapper,如果我们想要进行的对数据库的操作在mapper中没有对应的接口函数:比如生成的mapper接口中没有按照姓名及性别混合条件查询。我们的解决办法是:使用逆向工程生成的对应表的Example文件。
1.使用mybatis逆向工程生成的po类中包含UserExample文件(我的数据库表名为User). 2. 创建UserExample对象,然后对加入条件.对应的测试代码为: /* * 通过姓名和 ...
- CoreImage
[CoreImage] CIContext is an object through which Core Image draws the results produced by a filter. ...
- ScreenCapture手动卸载教程-Xproer.ScreenCapture
此教程包含WindowsXP,Windows7(x86) ,Windows7(x64),Firefox,Chrome卸载教程. 1.1. 手动卸载控件-Windows XP 主要步骤如下: 1.关闭所 ...
- RocketMQ服务器监控误区
请不要监控10912端口 case: result: 监控10912端口会导致HAService异常,新起线程,吃掉内存,无限次监控虚拟机将宕机! 时间上是直接因果关系. 监控10911 和 9876 ...
- Swift实现UIKit Dynamic动画
iOS7引入了UIKit Dynamics,可以帮助开发者开发出更接近真实世界的动画效果.之前,用户如果要做出这样的效果,需要话很多的时间在物理计算和Core Animation上.现在,所有的一切都 ...
- Appium之打开应用时提示框处理
当打开一个应用时,会有一个无关紧要的提示框,如果要继续操作,需要先关闭提示框,如下图(如新用户福利提示): 此时,如果你直接用Appium inspector或者Android uiautomator ...
- 面试经验之——HE集团,YZ科技
上周去了HE集团面试,该集团是做车辆辅助驾驶系统的,最终目标瞄准的是自动驾驶,加上再之前在YZ科技的面试经验,有些关于车辆驾驶上的心得想聊聊. 首先说说两个企业的面试情况吧.YZ科技中的两个技术聊天都 ...