POJ1066 Treasure Hunt
阿新 • • 發佈:2018-11-19
嘟嘟嘟
題意看題中的圖就行:問你從給定的點出發最少需要穿過幾條線段才能從正方形中出去(邊界也算)。
因為\(n\)很小,可以考慮比較暴力的做法。列舉在邊界中的哪一個點離開的。也就是列舉四周的點\((x, y)\),並和起點\((x_0, y_0)\)連成線段,求和多少條線段相交。
但是因為點可以是實數,所以不知道怎麼列舉。不過想想就知道,同一個區間中的點是等價的。因此我們只要列舉線段的端點即可。
至於判斷線段相交,用叉積實現:對於線段\(AB\)和\(CD\),如果\((\overrightarrow{AB} \times \overrightarrow{AC}) * (\overrightarrow{AB} \times \overrightarrow{AD}) < 0\)
(別忘了\(n = 0\)的情況……)
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<stack> #include<queue> using namespace std; #define enter puts("") #define space putchar(' ') #define Mem(a, x) memset(a, x, sizeof(a)) #define rg register typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const int maxn = 50; inline ll read() { ll ans = 0; char ch = getchar(), last = ' '; while(!isdigit(ch)) last = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); if(last == '-') ans = -ans; return ans; } inline void write(ll x) { if(x < 0) x = -x, putchar('-'); if(x >= 10) write(x / 10); putchar(x % 10 + '0'); } int n; struct Vec { db x, y; db operator * (const Vec& oth)const { return x * oth.y - oth.x * y; } }; struct Point { db x, y; Vec operator - (const Point& oth)const { return (Vec){x - oth.x, y - oth.y}; } }a[maxn], b[maxn], P; int solve(Point A, Point B) { Vec AB = B - A; int ret = 0; for(int i = 1; i <= n; ++i) { Vec AC = a[i] - A, AD = b[i] - A; Vec CD = b[i] - a[i], CB = B - a[i]; if((AB * AC) * (AB * AD) < -eps && (CD * AC) * (CD * CB) > eps) ret++; } return ret; } int ans = INF; int main() { n = read(); for(int i = 1; i <= n; ++i) a[i].x = read(), a[i].y = read(), b[i].x = read(), b[i].y = read(); scanf("%lf%lf", &P.x, &P.y); for(int i = 1; i <= n; ++i) { ans = min(ans, solve(a[i], P)); ans = min(ans, solve(b[i], P)); } if(!n) ans = 0; printf("Number of doors = "); write(ans + 1), enter; return 0; }