Codeforces Beta Round #13 D. Triangles
本番中に解けなかった問題シリーズ。今更ですが,前回のCodeforcesより。
問題
- 平面上にN個の赤い点とM個の青い点があって,NもMも最大500。
- 赤い点からなる三角形のうち,内部に青い点を含まないものの数は?
- 制約として,どの3点も同一直線上にはない
解法
- あまりに分からなかったのでEditorialを参考に実装。O(N^2(N+M))
- 現在見ている辺との最小の偏角を持つ点の更新部分は,angleで角度計算をするとTLEでした
- 外積を使った位置関係の比較にしたらAcceptに
- ちなみに,コードはローカルでのテスト簡単化のため複数ケース対応で書いています。
#include <iostream> #include <vector> #include <algorithm> #include <complex> using namespace std; typedef complex<double> P; double cross(P a, P b) { return imag(conj(a)*b); } double angle(P a, P b) { return arg(conj(a)*b); } int main(){ int N, M; P pt[1000]; while(cin >> N >> M){ int ans = 0; double x, y; for(int i=0;i<N+M;i++) { cin >> x >> y; pt[i] = P(x,y); } for(int i=0;i<N;i++){ vector< pair<double, int> > vp; for(int j=i+1;j<N+M;j++) vp.push_back(make_pair(angle(pt[i+1]-pt[i], pt[j]-pt[i]), j)); sort(vp.begin(), vp.end()); for(int j=0;j<vp.size();j++){ int idx = vp[j].second; if(!(idx < N)) continue; int blueIdx = -1; for(int k=1;k<vp.size();k++){ int idx2 = vp[(j+k)%vp.size()].second; if(cross(pt[idx2]-pt[idx], pt[i]-pt[idx]) < 0.0) break; if(blueIdx == -1 || cross(pt[idx2]-pt[idx], pt[blueIdx]-pt[idx]) < 0.0){ if(idx2 < N) ans++; else blueIdx = idx2; } } } } cout << ans << endl; } }