SWUST OJ 249凸包面积 分治法解法二,指针升级版

在这里插入图片描述

AC大吉
AC神符保佑你

题目描述

在这里插入图片描述在这里插入图片描述思路:
见另一篇文章分治法求凸包
先分为上下两个包,然后使用分治法递归求解面积
求面积的方法,先找顶点,把面积保留,然后对顶点与底边划分出来的两个三角形递归求面积
代码如下

#include<iostream>
#include<stdio.h>
using std::cin;
struct Node
{
	int x;
	int y;
};
Node p[105];
int calSquareS(int i, int j, int k) {
	int s= p[i].x * p[j].y + p[j].x * p[k].y + p[k].x * p[i].y - p[i].y * p[j].x - p[j].y * p[k].x - p[k].y * p[i].x;
	if(s>0) return s;
	if(s<0) return (-1)*s;
}

//1在上方,0在下方,-1在直线上
int isAbove(int i, int j, int amb) {
	int answer = (p[j].y - p[i].y) * (p[amb].x - p[i].x) - (p[amb].y - p[i].y) * (p[j].x - p[i].x);
	if (answer == 0) return -1;
	if(answer < 0) return 1;
	if(answer >0 )return 0;
}
int doMerge(int* g,int n,int min,int max) {
	if (n == 0) return 0;
	int s = calSquareS(min, max, *(g));
	if (n == 1) return s;
	//找最高
	int maxS = s,maxP=*g;
	for (int i = 1; i < n; i++) {
		s = calSquareS(min, max, *(g + i));
		if (maxS < s) {
			maxS = s;
			maxP = *(g+i);
		}
	}
	//划分包递归计算
	int left[105],right[105],numL=0,numR=0;
	for (int i = 1; i < n; i++) {
		if (*(g + i) == maxP) continue;
		//丢掉正下方
		if (p[*(g + i)].x < p[maxP].x) {
			left[numL] = *(g + i);
			numL++;
		}
		if (p[*(g + i)].x > p[maxP].x) {
			right[numR] = *(g + i);
			numR++;
		}
	}
	return doMerge(left, numL, min, maxP) +doMerge(right, numR, maxP, max) + maxS;
}


void calS() {
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> p[i].x >> p[i].y;
	}
	// 上下包
	int min = 0, max = 0;
	for (int i = 0; i < n; i++) {
		if (p[i].x < p[min].x) min = i;
		if (p[i].x > p[max].x) max = i;
	}
	//分上下包
	int under[105], undi = 0;
	int above[105], aboi = 0;
	for (int i = 0; i < n; i++) {
		if (i == min || i == max) {
			continue;
		}
		int isA = isAbove(min, max, i);
		if (isA==1) {
			above[aboi] = i;
			aboi++;
		}
		else if(isA==0)
		{
			under[undi] = i;
			undi++;
		}
	}
	//计算
	int aboveS = doMerge(above, aboi,min,max);
	int unserS = doMerge(under, undi,min,max);
	printf("%.1f\n", (aboveS + unserS) / 2.0);
}
int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		calS();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44494373/article/details/105747767