65,210
社区成员
发帖
与我相关
我的任务
分享
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
using namespace std;
struct node {
int x;
int y;
}data[1001];
int _max = 1;
bool isVis[1001];
int n;
int order[1001]; //存放已经访问的点,按访问顺序存放
//判断旋转角度是否小于等于180度
bool angle_can(int p1, int p2, int p3) {
if(data[p2].x == data[p3].x) {
if(data[p2].y >= data[p3].y && data[p1].x <= data[p2].x) return true;
if(data[p2].y <= data[p3].y && data[p1].x >= data[p2].x) return true;
return false;
}
if(data[p1].x == data[p2].x) {
if(data[p1].y <= data[p2].y && data[p1].x <= data[p3].x) return true;
if(data[p1].y >= data[p2].y && data[p1].x >= data[p3].x) return true;
return false;
}
if(data[p1].x == data[p3].x) {
if(data[p1].y <= data[p3].y && data[p1].x >= data[p2].x) return true;
if(data[p1].y >= data[p3].y && data[p1].x <= data[p2].x) return true;
return false;
}
float k12 = (data[p1].y - data[p2].y) / (float)(data[p1].x - data[p2].x);
if(data[p1].x > data[p2].x && data[p3].y >= k12 * (data[p3].x - data[p1].x) + data[p1].y) return true;
if(data[p1].x < data[p2].x && data[p3].y <= k12 * (data[p3].x - data[p1].x) + data[p1].y) return true;
return false;
}
double multiply(node& sp, node& ep, node& op) {
return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
}
//判断方法为快速排斥实验跟跨立实验
//如果两条线段相交就返回false,通过order数组来构造线段
//其中最后一条肯定不会与新加入的线段相交(除了那顶点)
bool line_can(int p, int count) {
if(count <= 1) return true;
//当新加入的线段的终点为起点时(第1个点),则不用判断从第一个点出发的线段
if(p != 0) {
if((max(data[p].x, data[order[count]].x) >= min(data[0].x, data[order[0]].x))&&
(max(data[0].x, data[order[0]].x) >= min(data[p].x, data[order[count]].x))&&
(max(data[p].y, data[order[count]].y) >= min(data[0].y, data[order[0]].y))&&
(max(data[0].y, data[order[0]].y) >= min(data[p].y, data[order[count]].y))&&
(multiply(data[0], data[order[count]], data[p]) * multiply(data[order[count]], data[order[0]], data[p]) >= 0)&&
(multiply(data[p], data[order[0]], data[0]) * multiply(data[order[0]], data[order[count]], data[0]) >= 0))
return false;
}
//判断以访问的点依次构成的线段与新加入的线段是否相交,
//其中最后一条肯定不会与新加入的线段相交(除了那顶点),故不用判断。
for(int i = 0; i <= count - 2; i++) {
if((max(data[p].x, data[order[count]].x) >= min(data[order[i]].x, data[order[i + 1]].x))&&
(max(data[order[i]].x, data[order[i + 1]].x) >= min(data[p].x, data[order[count]].x))&&
(max(data[p].y, data[order[count]].y) >= min(data[order[i]].y, data[order[i + 1]].y))&&
(max(data[order[i]].y, data[order[i + 1]].y) >= min(data[p].y, data[order[count]].y))&&
(multiply(data[order[i]], data[order[count]], data[p]) * multiply(data[order[count]], data[order[i + 1]], data[p]) >= 0)&&
(multiply(data[p], data[order[i + 1]], data[order[i]]) * multiply(data[order[i + 1]], data[order[count]], data[order[i]]) >= 0))
return false;
}
return true;
}
void dfs(int last, int cur, int count) {
if(cur == 0) {
_max = max(_max, count - 1);
return ;
}
for(int i = 0; i < n && _max != n - 1; i++) {
if(!isVis[i] && angle_can(last, cur, i) && line_can(i, count)) {
isVis[i] = true;
order[count + 1] = i;
dfs(cur, i, count + 1);
isVis[i] = false;
}
}
}
int main() {
freopen("C:/Users/Alfred/Desktop/1.txt", "r", stdin);
cin >> n;
memset(isVis, false, sizeof(isVis));
for(int i = 0; i < n; i++) {
cin >> data[i].x >> data[i].y;
}
for(int i = 1; i < n && _max != n - 1; i++) {
if(angle_can(0, 1, i)) {
isVis[i] = true;
order[0] = i;
dfs(0, i, 0);
isVis[i] = false;
}
}
cout << _max << endl;
return 0;
}
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
using namespace std;
struct node {
int x;
int y;
}data[1001];
int _max = 0;
bool isVis[1001];
int n;
int order[1001]; //存放已经访问的点,按访问顺序存放
//叉积
int cp(int p1, int p2, int p3) {
int x1 = data[p3].x - data[p1].x;
int y1 = data[p3].y - data[p1].y;
int x2 = data[p2].x - data[p1].x;
int y2 = data[p2].y - data[p1].y;
return x1 * y2 - x2 * y1;
}
bool rotate_can(int p1, int p2, int p3) {
if(cp(p1, p2, p3) >= 0) return true;
return false;
}
bool isIn(int point, int beg, int end) {
if(data[point].x >= min(data[beg].x, data[end].x) &&
data[point].x <= max(data[beg].x, data[end].x) &&
data[point].y >= min(data[beg].y, data[end].y) &&
data[point].y <= max(data[beg].y, data[end].y))
return true;
return false;
}
bool isCross(int p1, int p2, int p3, int p4) {
int d1 = cp(p3, p4, p1);
int d2 = cp(p3, p4, p2);
int d3 = cp(p1, p2, p3);
int d4 = cp(p1, p2, p4);
if(d1 * d2 < 0 && d3 * d4 < 0) return true;
if(d1 == 0 && isIn(p1, p3, p4)) return true;
if(d2 == 0 && isIn(p2, p3, p4)) return true;
if(d3 == 0 && isIn(p3, p1, p2)) return true;
if(d4 == 0 && isIn(p4, p1, p2)) return true;
return false;
}
bool line_can(int p, int count) {
if(count <= 1) return true;
if(p != 0 && isCross(0, order[0], order[count], p))
return false;
for(int i = 0; i <= count - 2; i++) {
if(isCross(order[i], order[i + 1], order[count], p))
return false;
}
return true;
}
void dfs(int last, int cur, int count) {
if(cur == 0) {
_max = max(_max, count);
return;
}
for(int i = 0; i < n && _max != n - 1; i++) {
if(!isVis[i] && rotate_can(last, cur, i) && line_can(i, count)) {
isVis[i] = true;
order[count + 1] = i;
dfs(cur, i, count + 1);
isVis[i] = false;
}
}
}
int main() {
//freopen("C:/Users/Alfred/Desktop/1.txt", "r", stdin);
memset(isVis, false, sizeof(isVis));
cin >> n;
for(int i = 0; i < n; i++) {
cin >> data[i].x >> data[i].y;
}
isVis[1] = true;
order[0] = 1;
dfs(0, 1, 0);
cout << _max << endl;
return 0;
}