题目链接:点击打开链接
题目大意:一个正方形的墓葬内有n堵墙,每堵墙的两个顶点都在正方形的边界上,现在这些墙将墓葬分割成了很多小空间,已知正方形内的一个点上存在宝藏,现在我们要在正方形的外面去得到宝藏,对于每个小空间,我们可以炸开它的任意一条边的中点,现在给出每堵墙的两个节点的坐标和宝藏的坐标,问如果要得到宝藏,需要炸的墙数最少是多少。
枚举正方形边界上的点作为进入正方形的节点,由这个点向宝藏连出一条线段,这条线段和多少个墙相交,那么就需要炸坏多少个墙,找出一个最小的值。
原因,因为每堵墙的两个节点都在边界上,所以如果和墙相交,那么就一定要跨过这道墙,所以需要炸掉它。
一定要是规范相交,因为如果枚举的点如果是一堵墙的节点,那么这堵墙是不应该被计算的。
(应该是枚举出边界上的小空间的中点,为了省事,直接枚举所有的点。)
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std ; #define eps 1e-8 #define zero(x) (((x) > 0 ? (x) : (-x)) < eps) struct Point { double x, y; }; struct Line { Point a, b; }l[35], len[4]; int n ; double xmult(Point p1, Point p2, Point p) { return (p1.x-p.x)*(p2.y-p.y) - (p2.x-p.x)*(p1.y-p.y); } double dmult(Point p1, Point p2, Point p) { return (p1.x-p.x)*(p2.x-p.x) + (p1.y-p.y)*(p2.y-p.y); } double distance(Point p1, Point p2) { return sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y)); } int opposite_side(Point p1,Point p2,Line l) { return xmult(l.a, p1, l.b)*xmult(l.a, p2, l.b) < -eps; } int intersect_ex(Line u, Line v) { return opposite_side(u.a, u.b, v) && opposite_side(v.a, v.b, u); } int solve(Line len) { int i, num = 0; for(i = 0; i < n; i++) { if( intersect_ex(l[i],len) ) num++; } return num; } int main() { int i , ans ; while( scanf("%d", &n) != EOF ) { ans = n ; for(i = 0; i < n; i++) { scanf("%lf %lf %lf %lf", &l[i].a.x, &l[i].a.y, &l[i].b.x, &l[i].b.y); } scanf("%lf %lf", &len[0].a.x, &len[0].a.y) ; len[1] = len[2] = len[3] = len[0]; len[0].b.y = len[3].b.x = 100 ; len[1].b.y = len[2].b.x = 0 ; for(i = 0; i <= 100; i++) { len[0].b.x = len[3].b.y = len[1].b.x = len[2].b.y = i ; ans = min(ans, solve(len[0])); ans = min(ans, solve(len[1])); ans = min(ans, solve(len[2])); ans = min(ans, solve(len[3])); } ans++ ; printf("Number of doors = %d\n", ans) ; } return 0 ; }