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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章