11665:Chinese Ink

問題文
http://uva.onlinejudge.org/external/116/11665.html

いくつかの多角形(凸とは限らない)を墨で塗りつぶしたときいくつの多角形ができるか求めよ。





























点-多角形包含判定。本番はライブラリが間違ってたらしく通せなかった。spaghetti sourceさんを参考になおした。

#include<cmath>
#include<algorithm>
#include<iostream>
#include<vector>
#include<climits>
#include<cfloat>
#include<sstream>
#include<string>
#define curr(P, i) P[(i) % P.size()]
#define next(P, i) P[(i+1) % P.size()]
   
using namespace std;
   
double EPS = 1e-10;

double add(double a, double b){
  if(abs(a+b) < EPS * (abs(a)+abs(b)))return 0;
  return a+b;
}
   
struct point{
  double x, y;
  point(){}
  point(double x,double y) : x(x) , y(y){}
   
  point operator + (point p){
    return point(add(x,p.x), add(y,p.y));
  }
   
  point operator - (point p){
    return point(add(x,-p.x), add(y,-p.y));
  }
};
   
double dot(point a, point b) {return (a.x * b.x + a.y * b.y);}
double cross(point a, point b) {return (a.x * b.y - a.y * b.x);}
double norm(point a){return sqrt(a.x*a.x+a.y*a.y);}
   
int is_point_on_line(point a, point b, point c) {
  return cross(b-a, c-a)==0.0 &&
         (dot(b-a, c-a) > -EPS) &&
         (dot(a-b, c-b) > -EPS);
}
   
   
int is_intersected_ls(point a1, point a2, point b1, point b2) {
   
  if(cross(a1-a2,b1-b2)==0){
    return is_point_on_line(a1,a2,b1) || is_point_on_line(a1,a2,b2)
        || is_point_on_line(b1,b2,a1) || is_point_on_line(b1,b2,a2);
  }
  else {
    return ( cross(a2-a1, b1-a1) * cross(a2-a1, b2-a1) < EPS ) &&
           ( cross(b2-b1, a1-b1) * cross(b2-b1, a2-b1) < EPS );
  }
}

int contain(point p,vector<point>pol){
  bool in=false;
  for(int i=0;i<pol.size();i++){
    point a=curr(pol,i)-p,b=next(pol,i)-p;
    if(a.y>b.y)swap(a,b);
    if(a.y<=0 && 0<b.y && cross(a,b)<0)in=!in;
    if(cross(a,b)==0 && dot(a,b)<=0)return 2;
  }
  return in?1:0;
}
   
bool crossPol(vector<point> pol1, vector<point> pol2){
     
  for(int i=0;i<pol1.size();i++)
    if(contain(pol1[i],pol2))return true;
     
  for(int i=0;i<pol2.size();i++)
    if(contain(pol2[i],pol1))return true;
     
  for(int i=0;i<pol1.size();i++)
    for(int j=0;j<pol2.size();j++)
      if(is_intersected_ls(pol1[i],next(pol1,i),pol2[j],next(pol2,j)))return true;
     
  return false;
}
 
vector<point>pol[100];
bool fg[100];
int n;
void rec(int m){
  fg[m]=true;
  for(int i=0;i<n;i++)
    if(!fg[i]&&crossPol(pol[m],pol[i]))rec(i);
}

int main(void){
  
  while(cin >> n,n){
    cin.ignore();
    
    for(int i=0;i<n;i++)pol[i].clear();
    for(int i=0;i<n;i++){
      string str;
      getline(cin,str);
      stringstream ss;
      ss << str;
      int a,b;
      while(ss >> a, ss >> b)
	pol[i].push_back(point(a,b));
    }
    
    int cnt=0;
    fill(fg,fg+100,false);
    for(int i=0;i<n;i++)if(!fg[i])rec(i),cnt++;
    
    cout << cnt << endl;
  }
  return 0;
}