読者です 読者をやめる 読者になる 読者になる

土下座しながら探索中

主に競技プログラミング

UVa 10382 : Watering Grass

問題リンク:http://uva.onlinejudge.org/external/103/10382.html

問題概要:

解法:
円と長方形が交差する場所のx座標を計算で求める
円の中心点の座標を(x,y)、円の半径をrとすると
円と長方形が交差する場所のx座標(以下 nx)は以下の通り
nx = +sqrt(r*r-(l/2)*(l/2)),-sqrt(r*r-(l/2)*(l/2))
この情報を円毎に作っておく

全ての場所をスプリンクラーがカバーしないといけないため、
左(または右)から貪欲に決める亊ができる
最初まだカバーされていない点をx = 0とする
左から右へ向かうとすると、
長方形と交差する場所の間にxを含むような円の中でもっとも右にすすめる円を選ぶ
そしてxにその右の場所を代入する
これをxがwをこえるまで繰り返す

その過程でどうしても全てをカバーできない亊が分かったら-1と出力し終了する

コード:

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<29)
#define EPS (1e-10)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;

struct P
{
  double left,right;
  P(double left=inf,double right=inf):left(left),right(right){}
};

struct Point
{
  double x,y;
  Point(double x=inf,double y=inf):x(x),y(y){}
};

int n;
double h,w;
vector<Point> vec;

void compute()
{
  P cs[n];
  rep(i,n)
    {
      double y = h * 0.5;
      assert(vec[i].y*vec[i].y - y * y >= 0);
      double x = sqrt(vec[i].y*vec[i].y - y*y);
      cs[i].right = vec[i].x+x;
      cs[i].left  = vec[i].x-x;
    }

  double x = 0;
  double pre_x = -1;
  int cnt = 0;
  while(!equals(x,w) && x < w)
    {
      int pos = -1;
      rep(i,n)
	{
	  double L = cs[i].left;
	  double R = cs[i].right;
	  if(L <= x && x <= R)
	    {
	      if(pos == -1)pos = i;
	      else
		{
		  if(cs[pos].right < R)
		    {
		      pos = i;
		    }
		}
	    }
	}

      if(pos == -1)
	{
	  cout << -1 << endl;
	  return;
	}
      pre_x = x;
      x = cs[pos].right;
      if(equals(pre_x,x))
	{
	  cout << -1 << endl;
	  return;
	}

      x = cs[pos].right;
      cnt++;
    }
  cout << cnt << endl;
}

int main()
{
  while(scanf("%d %lf %lf",&n,&w,&h) != EOF)
    {
      vec.resize(n);
      rep(i,n)scanf("%lf %lf",&vec[i].x,&vec[i].y);

      compute();

    }
  return 0;
}