swust oj凸包面积(0249)_分治法
来源:互联网 发布:xp网络开机自动打开 编辑:程序博客网 时间:2024/05/22 06:18
这道题本身不是很难哟,不要被吓到,然后就可以开始做了O(∩_∩)O~~
题目:
分治法思路:见http://download.csdn.net/download/xiao_huang2013/7414317
先预排序,预排序后最左和最右的点肯定是凸包中的点。然后可以递归的从内向外扩展凸包,在当前直线的2侧寻找最高点,
最高点肯定在凸包中,这里涉及到一些数学知识:
a,首先定义射线p1到p2的左侧:若p1 p2 p构成的顺序是逆时针,称p在射线的左侧
b,三角形p1 p2 p3的面积等于下列行列式的一半:
仅当p3在射线p1p2左侧时这个值才为正。
由此我们很容易求p1,p2左侧的最高点(离直线最远的点,这个点即凸包向外扩展得到的新顶点),得到一个最高点后,就得到了2条新边,继续向外扩展
那么写这个题的过程便可以是:
1.写主函数,输入
2.calSize函数,以最左右的两点为参数(令为p1,p2)
3.编写calSize函数,作用是调用calLSize、calRSize函数,分别用来求p1p2直线上下的面积
4.编写calLsize、calRSize函数
5.写calLsize时,判断方向,排除已经用掉的点,找到当前p点,根据求面积公式写函数求△pp1p2面积,替换顶点递归
5.定义p1->p2->p[i]逆时针为左,反之为右,因为刚好判断顺逆时针的叉乘结果的绝对值等于三角形面积的两倍,于是共用calArea(求面积)函数
tips:
判断两个平面向量构成的方向是顺时针还是逆时针:
a = (ax,ay) , b = (bx,by)
a X b = ax * by - ay *bx
a X b > 0则是逆时针,< 0 则是顺时针
已知三点坐标求围成三角形的面积(也是用叉乘,所以我写在同一个函数里的,一起用):
ax = x1 - x2; ay = y1 - y2; bx = x2 - x3; by = y2 - y3;
a X b = ax * by - ay *bx
s = 0.5 * fabs((double)(a X b));//fabs为取绝对值,需要加上#include<math.h>
错误提示:XX函数找不到标识符
改正:写函数时如果调用在先定义在后,需要先声明,再调用(声明 != 调用)
错误提示:有多个重载函数XX实例与参数列表匹配
改正:看是否符合公式使用条件,如fabs只用于浮点数
测试数据:(不包括数据组数T)
//正方形中间的点
5
0 0
2 0
0 2
2 2
1 1
//多组,记得初始化used[]
5
0 0
1 0
0 1
1 2
2 1
//比较的时候写成if (x[j] > maxX)maxX = j;应该是x[j] > x[maxX],min也写错了
10
0 0
10 10
0 10
10 0
3 5
6 3
4 8
8 3
9 1
9 9
10
0 0
10 10
10 0
0 10
5 5
4 8
5 0
10 5
1 8
6 2
//答案0.0 1.0 0.5 6.0
4
1
184 225
4
0 0
0 1
1 0
1 1
3
0 0
0 1
1 0
6
0 2
1 1
0 0
2 1
3 0
3 2
代码:
#include<stdio.h>//分治法#include<iostream>using namespace std;#include<math.h> int x[110],y[110],used[110]={0};double size; double TriangelSize(int i,int j,int k){ int x1=x[i],x2=x[j],x3=x[k],y1=y[i],y2=y[j],y3=y[k]; used[i] = used[j] = used[k] = 1; return 0.5*fabs( (double)(x2-x1)*(y3-y2)-(y2-y1)*(x3-x2) );} //定义:使得原两点与新的点连线方向为逆时针的,为LSide,即左,calArea>0则逆,<则顺double calArea(int p1,int p2,int i){ int x1=x[p1],y1=y[p1],x2=x[p2],y2=y[p2],x3=x[i],y3=y[i]; return 0.5*((x2-x1)*(y3-y2)-(x3-x2)*(y2-y1));} void calLSize(int n,int p1,int p2){ int p=-1; double sizeMax=-1; for (int i = 0; i < n; i++) { if (used[i] == 1 || calArea(p1,p2,i) <= 0 || i == p1 || i == p2)continue;//不符合构成新三角形的条件的点 if (calArea(p1,p2,i) > sizeMax) { sizeMax = calArea(p1,p2,i); p = i; } } if (p == -1)return; size += TriangelSize(p1,p2,p); calLSize(n,p1,p); calLSize(n,p,p2);} void calRSize(int n,int p1,int p2){ int p=-1; double sizeMax=-1; for (int i = 0; i < n; i++) { if (used[i] == 1 || calArea(p1,p2,i) >= 0 || i == p1 || i == p2)continue;//不符合构成新三角形的条件的点 if (-calArea(p1,p2,i) > sizeMax) { sizeMax = -calArea(p1,p2,i); p = i; } } if (p == -1)return; size += TriangelSize(p1,p2,p); calRSize(n,p1,p); calRSize(n,p,p2);} void calSize(int n,int p1,int p2){ calLSize(n,p1,p2); calRSize(n,p1,p2);} int main(){ int T,n,i,j,minX,maxX; cin>>T; for(i = 0; i < T; i++) { size = 0; cin>>n; for(j = 0; j < n; j++) { cin>>x[j]>>y[j]; used[j] = 0; } minX = maxX = x[0]; for(j = 0; j < n; j++) { if (x[j] > x[maxX])maxX = j; if (x[j] < x[minX])minX = j; } calSize(n,minX,maxX); printf("%.1lf\n",size); } return 0;}
本文地址:http://blog.csdn.net/qq_33810513/article/details/51440320
written by Sneexy
o(≧v≦)o~~AC了好兴奋
- swust oj凸包面积(0249)_分治法
- swust 最小凸包的面积
- swustoj----249凸包的面积(分治法)
- 凸包面积(0249)
- SWUST OJ 1025
- SWUST OJ 1137 STICKS
- SWUST OJ 1804 二进制
- swust OJ 1515
- swust OJ 1619 中位数
- SWUST OJ 2285
- swust.oj 0259
- swust.oj 0964
- swust.oj,0541
- swust.oj.319
- swust.oj.1013
- swust.oj.1015
- swust.oj.1072
- swust.oj.1076
- VMware CentOS自动联网配置
- iOS开发之AsyncSocket使用教程
- 第三次课总结
- igllib 105_Overlays
- InvokeRequired和Invoke
- swust oj凸包面积(0249)_分治法
- 在Ubuntu10.10下升级内核到2.6.36使用systemtap
- 单链表的实现及其操作(java,练手)
- WordPress主题 Olam 资源下载数字下载高级商城中文主题[v1.3版]
- 判断字符串的字符数
- 智能聊天机器人之图灵机器人
- AndroidStudio中删除module
- ConnectivityManager网络连接状态
- 格式的输入与输出