题解:P1153 点和线
_Liangyi2e8_ · · 题解
题解:P1153 点和线
题意简述
给你平面上的
这又有什么好简述的。
思路
考虑深搜,由于
在此基础上考虑剪枝,不仅是因为能提高效率,还因为加了剪枝后代码稍微好写一些(确信)。
首先定义 dfs(int dep),其中 dep 表示现在确定了多边形的前
判断两条线段是否有公共点非常简单,先考虑如何判断两条线段
int n;
bool check(point a, point b, point c, point d) {
if(((b - a) * (c - a)) * ((b - a) * (d - a)) <= 0 && ((d - c) * (a - c)) * ((d - c) * (b - c)) <= 0) return true;
return false;
}
其中代码中 b - a 表示由点
搜索共
代码
#include<bits/stdc++.h>
//#define int long long
using namespace std;
struct point { //定义点 or 向量
int x, y;
point operator + (point B) const { //向量加法(这不废话吗)
return point {x + B.x, y + B.y};
}
point operator - (point B) const { //向量减法(废话)
return point {x - B.x, y - B.y};
}
int operator * (point B) const { //向量叉积
return x * B.y - y * B.x;
}
} a[15];
int n;
bool check(point a, point b, point c, point d) { //判断线段 AB 与 CD 是否有公共点
if(((b - a) * (c - a)) * ((b - a) * (d - a)) <= 0 && ((d - c) * (a - c)) * ((d - c) * (b - c)) <= 0) return true;
return false;
}
bool vis[15];
point b[15];
int ans;
void dfs(int dep) { //搜索(还是废话)
if(dep == n) { //搜完后
for(int j = 2; j < dep - 1; j++) {
if(check(b[j], b[j - 1], point {0, 0}, b[dep - 1])) {
return ;
}
}
++ans; //记录答案
return ;
}
bool flag;
for(int i = 1; i < n; i++) {
if(vis[i]) continue;
flag = true;
for(int j = 1; j < dep - 1; j++) {
if(check(b[j], b[j - 1], a[i], b[dep - 1])) { //与之前选的边有公共点
flag = false;
break;
}
}
if(flag) {
vis[i] = true;
b[dep] = a[i];
dfs(dep + 1); //递归
vis[i] = false; //回溯
}
}
}
signed main() {
n = 1;
cin >> a[n].x >> a[n].y;
while(a[n].x || a[n].y) {
++n;
cin >> a[n].x >> a[n].y;
}
dfs(1);
cout << (ans >> 1) << endl;
return 0;
}
AC 记录。