背景:
地圖上給出若干個點,求出這些點圍繞的最大面積,並按順序排列。
原理:
暴力枚舉,由反證法得x軸最小的值一定是圍繞的邊界點,將其作爲起點,在尋找下一個點符合其餘的點均在這兩個點構成直線的一側。最後回到初始點時返回。
向量和點關係算法:
S(P1,P2,P3)=|y1 y2 y3|= (x1-x3)*(y2-y3)-(y1-y3)*(x2-x3)
當P1P2P3逆時針時S爲正的,當P1P2P3順時針時S爲負的。
因爲座標經度需求大,爲了精確計算使用了函數實現四則運算。
function mul(a, b) {
var c = 0,
d = a.toString(),
e = b.toString();
try {
c += d.split(".")[1].length;
} catch (f) {}
try {
c += e.split(".")[1].length;
} catch (f) {}
return (
(Number(d.replace(".", "")) * Number(e.replace(".", ""))) / Math.pow(10, c)
);
}
function sub(a, b) {
var c, d, e;
try {
c = a.toString().split(".")[1].length;
} catch (f) {
c = 0;
}
try {
d = b.toString().split(".")[1].length;
} catch (f) {
d = 0;
}
return (e = Math.pow(10, Math.max(c, d))), (mul(a, e) - mul(b, e)) / e;
}
輸入數據結構示例:
lines[{x:"123",y:"456"},{x:"123",y:"456"}]
具體實現:
//範圍算法
ConvexHull(lines) {
//排序去重
for (let i = 0; i < lines.length; i++) {
for (let j = 0; j < lines.length - i - 1; j++) {
if (lines[j].x > lines[j + 1].x) {
let tamp = lines[j];
lines[j] = lines[j + 1];
lines[j + 1] = tamp;
}
if (lines[j].x == lines[j + 1].x && lines[j].y == lines[j + 1].y) {
lines.splice(j + 1, 1);
j--;
}
}
}
let result = [];
let index = 1;
result.push(lines[0]);
while (true) {
let point = this.findNext(lines, result[index - 2], result[index - 1]);
if (point == null) break;
result.push(point);
if (point.x == lines[0].x && point.y == lines[0].y) {
break;
}
if (index > lines.length + 2) {
break;
}
index++;
}
return result;
},
findNext(lines, start, node) {
for (let i = 0; i < lines.length; i++) {
if (start != null && start.x == lines[i].x && start.y == lines[i].y) {
continue;
}
if (node != null && node.x == lines[i].x && node.y == lines[i].y) {
continue;
}
let search = true;
let target = -9999;
for (let j = 0; j < lines.length; j++) {
if (i == j) continue;
if (node != null && node.x == lines[j].x && node.y == lines[j].y) {
continue;
}
let left =
sub(node.x, lines[j].x) * sub(lines[i].y, lines[j].y) -
sub(node.y, lines[j].y) * sub(lines[i].x, lines[j].x) >
0
? true
: false;
if (target == -9999) {
target = left;
}
if (left != target) {
search = false;
break;
}
}
if (search == true) {
return lines[i];
}
}
},