FZU2148 Moon Game(计算几何判断凸包)

题目大意:给n个二维坐标点,保证任意三点不共线,问能构成的不同凸四边形的个数。

解题思路

  • 思路1:找对角线段,相交则为凸四边形,否则为凹多边形;
  • 思路2:利用面积,如果为凹四边形其中必然存在一个由三点构成的三角形等于其他三个由三点构成的三角形的和,否则为凸多边形。给的是坐标,可以利用叉积公式计算三角形的面积。如果用海伦公式计算的话可能会精度问题导致WA,因为其中做了许多开根号。
  • 思路3:未完成,先把选进来的四个点按顺时针排序,仍然是利用叉积的结果判断两个向量的相对位置,如果大于0表示后面那个向量在前面向量的顺时针方向,小于0在逆时针方向,等于0两向量共线。其中需要找到一个多边形内部的一点,然后扫描一下。接着利用反余弦函数和向量点乘计算出夹角,然后判断内角和是否为360,其中反余弦函数范围在0~PI内。

Code

#include <iostream>
#include <math.h>
#include <algorithm>
#include <string.h>
#include <string>

using namespace std;
const int maxn = (int)3e1+5;
const double esp = 1e-6;

struct point {
	int x, y;
};

point tab[maxn];

/*
inline double calc_len (point& A, point& B) {
	return sqrt(1.0*(A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
}

inline double calc_area(double a, double b, double c) {
	double p = (a + b + c) / 2;
	return sqrt(1.0 * p * (p - a) * (p - b) * (p - c));
}
*/

inline double calc_area(point& A, point& B, point& C) {
	return fabs((B.x - A.x) * (C.y - A.y) - (B.y - A.y) * (C.x - A.x)) / 2.0;
}

double l1, l2, l3, l4, l5, l6;
double s1, s2, s3, s4;

int main() {
	int T, n;
	cin >> T;
	for (int i = 1; i <= T; i++) {
		cin >> n;
		for (int j = 0; j < n; j++) { //io
			cin >> tab[j].x >> tab[j].y;
		}
		int cnt = 0;
		for (int j = 0; j < n; j++) {
			for (int z = j + 1; z < n; z++) {
				for (int k = z + 1; k < n; k++) {
					for (int p = k + 1; p < n; p++) {
						/*
						l1 = calc_len(tab[j], tab[z]);
						l2 = calc_len(tab[j], tab[p]);
						l3 = calc_len(tab[z], tab[k]);
						l4 = calc_len(tab[j], tab[k]);
						l5 = calc_len(tab[k], tab[p]);
						l6 = calc_len(tab[p], tab[z]);

						s1 = calc_area(l1, l2, l6);
						s2 = calc_area(l1, l4, l3);
						s3 = calc_area(l2, l4, l5);
						s4 = calc_area(l3, l5, l6);
						*/
						s1 = calc_area(tab[j], tab[z], tab[k]);
						s2 = calc_area(tab[j], tab[z], tab[p]);
						s3 = calc_area(tab[j], tab[k], tab[p]);
						s4 = calc_area(tab[p], tab[z], tab[k]);
						if (fabs(s1 - s2 - s3 - s4) < esp || fabs(s2 - s1 - s3 - s4) < esp ||
						fabs(s3 - s2 - s1 - s4) < esp || fabs(s4 - s2 - s3 - s1) < esp) {
							continue;
						}
						cnt++;
					}
				}
			}
		}
		cout << "Case " << i << ": " << cnt << endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小胡同的诗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值