2014年2月15日土曜日

AOJ0187 Stoning Fortune

解法


どれか二線の交点がなかったら凶。
あったら、3つの交点を求めてヘロンの公式S=√s(s-a)(s-b)(s-c)で面積を求めてはっぴー

ソース


int main(){
  L ls[3];
  int x1[3], y1[3], x2[3], y2[3];
  while( cin >> x1[0] >> y1[0] >> x2[0] >> y2[0], x1[0]|y1[0]|x2[0]|y2[0] ){
    for(int i = 1 ; i < 3 ; i++ ){
      cin >> x1[i] >> y1[i] >> x2[i] >> y2[i];
    }
    for(int i = 0 ; i < 3 ; i++ ){
      ls[i] = L( P( x1[i], y1[i]), P( x2[i], y2[i]));
    }
 
    G triangle(3);
    bool flag = true;
    for(int i = 0 ; i < 3 ; i++ ){
      const int NEXT = ( i + 1 ) % 3;
      if(!intersect( ls[i], ls[NEXT])){
        flag = false;
        break;
      }else{
        triangle[i] = crosspoint( ls[i], ls[NEXT]);
      }
    }
 
    double s = (abs(triangle[0]-triangle[1])+abs(triangle[1]-triangle[2])+abs(triangle[2]-triangle[0])) / 2;
    double area = sqrt(s * ( s - abs(triangle[0] - triangle[1])) * ( s - abs(triangle[1] - triangle[2])) * ( s - abs(triangle[2] - triangle[0])));
    if(!flag || area < EPS) cout << "kyo" << endl;
    else if(area < 100000) cout << "syo-kichi" << endl;
    else if(area < 1000000) cout << "kichi" << endl;
    else if(area < 1900000) cout << "chu-kichi" << endl;
    else cout << "dai-kichi" << endl;
  }
}

AOJ0091 Blur

解法


BFS。左上から見ていって、滴数 < 0か垂らしても残った時に枝刈りした。
これでVolume0全完。

ソース


#include<bits/stdc++.h>
using namespace std;

int q, mas[10][10];
int draw[][5][5] = {
  /*Small*/
  {{ 0, 0, 1, 0, 0},
   { 0, 1, 1, 1, 0},
   { 0, 0, 1, 0, 0}},
  //*midium*/
  {{ 0, 0, 1, 1, 1},
   { 0, 0, 1, 1, 1},
   { 0, 0, 1, 1, 1}},
  /*large*/
  {{ 0, 0, 1, 0, 0},
   { 0, 1, 1, 1, 0},
   { 1, 1, 1, 1, 1},
   { 0, 1, 1, 1, 0},
   { 0, 0, 1, 0, 0}},
};

bool check( int y, int x, int w){
  for(int i = 0 ; i < 5 ; i++ ){
    for(int j = 0 ; j < 5 ; j++ ){
      if(mas[y + i][x + j - 2] - draw[w][i][j] < 0) return false;
    }
  }
  return true;
}

void paint( int y, int x, int w){
  for(int i = 0 ; i < 5 ; i++ ){
    for(int j = 0 ; j < 5 ; j++ ){
      mas[y + i][x + j - 2] -= draw[w][i][j];
    }
  }
}

void repaint( int y, int x, int w){
  for(int i = 0 ; i < 5 ; i++ ){
    for(int j = 0 ; j < 5 ; j++ ){
      mas[y + i][x + j - 2] += draw[w][i][j];
    }
  }
}

bool rec( int y, int x, int n){
  if( n < 0 ) return false;
  if( y == 10 ) return n == 0;
  if( mas[y][x] == 0 ) return rec( y + (x == 9), (x + 1) % 10, n);
  for(int i = 0 ; i < 3 ; i++ ){
    if(!check( y, x, i)) continue;
    paint( y, x, i);
    if(rec( y, x, n - 1)){
      cout << x + (i == 1) << " " << y + 1 + (i == 2) << " " << i + 1 << endl;
      return true;
    }
    repaint( y, x, i);
  }
  return false;
}

int main(){
  cin >> q;
  for(int i = 0 ; i < 10 ; i++ ){
    for(int j = 0 ; j < 10 ; j++ ){
      cin >> mas[i][j];
    }
  }
  rec( 0, 0, q);
 }

2014年2月8日土曜日

AOJ0560 惑星探査

解法


二次元累積和を実装していい感じにやる

ソース


#include<iostream>  
#include<vector>  
#include<algorithm>  
#include<string>  
   
using namespace std;  
int mas[1001][1001][3];  
int main(){  
   
  int M, N, K;  
  string tmp = "JOI";  
   
  cin >> M >> N;  
  cin >> K;  
  for(int i = 1 ; i <= M ; i++ ){  
    for(int j = 1 ; j <= N ; j++ ){  
      char c;  
      cin >> c;  
      for(int k = 0 ; k < 3 ; k++ ){  
        mas[i][j][k] = mas[i-1][j][k] + mas[i][j-1][k] - mas[i-1][j-1][k];  
      }  
      mas[i][j][tmp.find(c)]++;  
    }  
  }  
  for(int i = 0 ; i < K ; i++ ){  
    int a, b, c, d;  
    cin >> a >> b >> c >> d;  
    for(int j = 0 ; j < 3 ; j++ ){  
      cout << (j?" ":"") << mas[c][d][j] + mas[a-1][b-1][j] - mas[a-1][d][j] - mas[c][b-1][j];  
    }  
    cout << endl;  
  }  
}  

AOJ1183 鎖中経路

解法


2つの円の交点を通る線分に交わっているか確かめながら、Dijkstraした。


ソース


#include<complex>
#include<algorithm>
#include<vector>
#include<map>
#include<iomanip>
#include<iostream>
#include<queue>
using namespace std;
#define fr first
#define sc second
 
struct line: public vector< complex<double> >{
  line(){};
  line( const complex<double>& a, const complex<double>& b){
    push_back(a);
    push_back(b);
  }
};
struct circle {
  complex<double> p; double r;
  circle():p(0,0),r(0){};
  circle(const complex<double> &p, double r) : p(p),r(r){}
};
 
typedef complex < double > P;
typedef line               L;
typedef pair < P, P >      Ls;
typedef vector< P >        G;
typedef vector< P >        Ps;
typedef vector< L >        LLL;
typedef circle             C;
const double EPS = 1e-9;
const double INF = 1e8;
 
bool   eq(P,P); //点:点 一緒か
double cross(P,P); //外積
double dot(P,P); //内積
int    ccw(P,P,P); //3点の位置関係
bool   parallel(L,L); // 直線//直線
bool   orthogonal(L,L); //直線⊥直線
bool   intersect(L,L); //線分:線分交差
bool   intersect(L,P); //線分:点交差
bool   intersect(Ls,Ls); //直線:直線交差
bool   intersect(Ls,L); //直線:線分交差
bool   intersect(Ls,P); //直線:点交差
int    intersect(C,L); //円:線分交点数
double distance(L,L); //線分:線分の距離
double distance(L,P); //線分:点の距離
double distance(P,P); //点:点の距離
double distance(Ls,P); //直線:点距離
double distance(Ls,Ls); //直線:直線距離
double distance(Ls,L); //直線:線分距離
P      crosspoint(L,L); //線分:線分交点計算
L      crosspoint(C,Ls); //円:直線交点計算
L      crosspoint(C,L); //円:線分交点計算
Ps     crosspoint(C,C); //円:円交点計算
int    contains(G,P); //GがPが包容か
double area2(G); //Gの面積
bool   isconvex(G); //凸性判定
Ps     convex(G); //凸包
 
 
namespace std {
  bool operator < (const P& a, const P& b) {
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
L llcomb(Ls a){
  L line( a.fr, a.sc);
  return line;
}
Ls llrcomb(L a){
  Ls line( a[0], a[1]);
  return line;
}
bool eq( P a, P b){
  return abs( a - b) < EPS;
}
double cross( P a, P b){
  return imag( conj(a) * b);
}
double dot( P a, P b){
  return real( conj(a) * b);
}
P projection( L l, P p) {
  double t = dot( p - l[0], l[0] - l[1]) / norm( l[0] - l[1]);
  return l[0] + t * ( l[0] - l[1]);
}
 
int ccw( P a, P b, P c){
  b -= a, c -= a;
  if(cross(b,c) > EPS)    return 1;  // a → b で 時計方向におれて c
  if(cross(b,c) < -EPS)    return -1; // a → b で 反時計方向におれて c
  if(dot(b,c) < -EPS)      return 2;  // c -- a -- b
  if(norm(b) < norm(c) - EPS) return -2; // a -- b -- c
                        return 0;  // a -- c -- b
}
bool intersect( L a, L b){
  return ccw( a[0], a[1], b[0]) * ccw( a[0], a[1], b[1]) <= 0 &&
    ccw( b[0], b[1], a[0]) * ccw( b[0], b[1], a[1]) <= 0;
}
bool intersect( L a, P p){
   return abs( a[0] - p) + abs( a[1] - p) - abs( a[1] - a[0]) < EPS;
}
bool intersect( Ls l, Ls m) {
  return abs(cross(l.sc-l.fr, m.sc-m.fr)) > EPS ||
         abs(cross(l.sc-l.fr, m.fr-l.fr)) < EPS;
}
bool intersect(Ls l, L s) {
  return cross( l.sc - l.fr, s[0] - l.fr) *      // s[0] is left of l
         cross( l.sc - l.fr, s[1] - l.fr) < EPS; // s[1] is right of l
}
bool intersect(Ls l, P p) {
  return abs( cross( l.sc - p, l.fr - p)) < EPS;
}
int intersect( C c, L l){
  if( norm( projection( l, c.p) - c.p) - c.r * c.r > EPS) return 0;
  const double d1 = abs( c.p - l[0]), d2 = abs( c.p - l[1]);
  if( d1 < c.r + EPS && d2 < c.r + EPS) return 0;
  if( d1 < c.r - EPS && d2 > c.r + EPS
      || d1 > c.r + EPS && d2 < c.r - EPS ) return 1;
  const P h = projection(l, c.p);
  if( dot( l[0] - h, l[1] - h) < 0) return 2;
  return 0;
}
double distance( L s, P p){
  P r = projection(s, p);
 
  if ( intersect( s, r)) return abs( r - p);
  return min( abs( s[0] - p), abs( s[1] - p));
}
double distance( L a, L b){
  if(intersect( a, b)) return 0;
  return min( min( distance( a, b[0]), distance( a, b[1])),
              min( distance( b, a[0]), distance( b, a[1])));
}
double distance( Ls l, P p) {
  return abs(p - projection( llcomb(l), p));
}
double distance( Ls l, Ls m) {
  return intersect(llcomb(l), llcomb(m)) ? 0 : distance(llcomb(l), m.fr);
}
double distance( Ls l, L s) {
  if (intersect(l, s)) return 0;
  return min(distance(l, s[0]), distance(l, s[1]));
}
double distance( P a, P b){
  return abs( a - b);
}
bool parallel( L a, L b){
  return abs( cross( a[1] - a[0], b[1] - b[0])) < EPS;
}
bool orthogonal( L a, L b){
  return dot( a[0] - a[1], b[0] - b[1]) < EPS;
}
#define curr(P,i) P[i]
#define next(P,i) P[(i+1)%P.size()]
#define prev(P, i) P[(i+P.size()-1) % P.size()]
enum { OUT, ON, IN };
int conteins(G Q, P p){
  bool in = false;
  for(int i = 0 ; i < Q.size() ; i++ ){
    P a = curr(Q,i) - p, b = next(Q,i) - p;
    if(imag(a) > imag(b)) swap(a,b);
    if(imag(a) <= 0 && 0 < imag(b) && cross(a,b) < 0) in = !in;
    if(cross(a,b) == 0 && dot(a,b) <= 0) return ON;
  }
  return in ? IN : OUT;
}
double area2(G p){
  double A = 0;
  for (int i = 0; i < p.size(); ++i){
    A += cross(curr(p, i), next(p, i));
  }
  return A;
}
bool isconvex(G p) {
  for (int i = 0; i < p.size(); ++i){
    if (ccw(prev(p, i), curr(p, i), next(p, i)) > 0) return false;
  }
  return true;
}
Ps convex(Ps ps) { //n>=3
  int k = 0;
  sort(ps.begin(), ps.end());
  Ps ch(2 * ps.size());
  for (int i = 0; i < ps.size(); ch[k++] = ps[i++]){
    while (k >= 2 and ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
  }
  for (int i = ps.size()-2, t = k+1; i >= 0; ch[k++] = ps[i--]){
    while (k >= t and ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
  }
  ch.resize(k-1);
  return ch;
}
P crosspoint(L l, L m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  return m[0] + B / A * (m[1] - m[0]);
}
L crosspoint( C c, Ls l) {
  const P hp = projection( llcomb(l), c.p), h =  hp - c.p;
  const double d2 = norm(h);
  P v = sqrt( c.r * c.r - d2) * ( l.sc - l.fr) / abs( l.sc - l.fr);
  return L(hp - v, hp + v);
}
L crosspoint( C c, L l) {
  if(intersect(c, l) == 2) return crosspoint(c, llrcomb(l));
  L ret = crosspoint(c, llrcomb(l));
  if(dot(l[0] - ret[0], l[1] - ret[0]) < 0) ret[1] = ret[0];
  else ret[0] = ret[1];
  return ret;
}
Ps crosspoint(C c1, C c2){
  double d = abs(c1.p - c2.p);
  double s = (c1.r + c2.r + d) / 2;
  double S = sqrt( s * ( s - c1.r) * ( s - c2.r) * ( s - d));
  double h = 2 * S / d;
  P v = ( c2.p - c1.p) / ( abs( c2.p - c1.p));
  double m = sqrt( c1.r * c1.r - h * h);
  Ps ret;
  ret.push_back( c1.p + m * v + h * v * P(0,1));
  ret.push_back( c1.p + m * v - h * v * P(0,1));
  return ret;
}
struct dC{
  double cost;
  P pos;
  int nowi,nowj;
  bool operator < (const dC &left) const {
    return cost > left.cost;
  }
};
L make_2_cross(C c1, C c2){
  Ps a(crosspoint( c1, c2));
  return L( a[0], a[1]);
}
 
int main(){
  C prev, now;
  int n;
 
  while(cin >> n , n){
    LLL ls;
 
    cin >> prev.p.real() >> prev.p.imag() >> prev.r;
    ls.push_back( L( prev.p, prev.p));
 
    for(int i = 1 ; i < n ; i++ ){
      cin >> now.p.real() >> now.p.imag() >> now.r;
      ls.push_back( make_2_cross( prev, now));
      prev = now;
    }
    ls.push_back( L( prev.p, prev.p)); // G
 
    priority_queue< dC > que;
    que.push((dC){ 0, ls[0][0], 0, 0});
    bool used[101][2] = {{}};
    double ret = INF;
    while(!que.empty()){
      dC p = que.top();
      que.pop();
      if(p.nowj == n){
        ret = p.cost;
        break;
      }
      if(used[p.nowj][p.nowi]++) continue;
      for(int i = 0 ; i < 2 ; i++ ){
        for(int j = p.nowj + 1 ; j <= n ; j++ ){
          L l = L( p.pos, ls[j][i]);
 
          bool flag = true;
          for(int k = j - 1 ; k > p.nowj ; k-- ){
            if(!intersect( l, ls[k])){
              flag = false;
              break;
            }
          }
          if(flag) que.push( (dC){ abs( l[0] - l[1]) + p.cost, l[1], i, j});
        }
      }
    }
    cout << fixed << setprecision(7) << ret << endl;
  }
}

AOJ1182 鉄道乗り継ぎ

解法


ワーシャった(小並感)
最初はワーシャって会社別に各駅までの最短距離を求める。
その次は、与えられたグラフを20000くらい(距離≦200 * 駅数≦100 より)までシュミレートして愚直に運賃を求める。
で、それを最初のグラフと照らし合わせながら、最短距離を運賃に変えたグラフにする。ついでに会社もまとめる。
最後にもう一回ワーシャって最安運賃を求める。

ソース


#include<iostream>
#include<queue>
#include<map>
 
using namespace std;
 
typedef pair < int , int > Pi;
const int INFTY = ( 1 << 28 );
 
int main(){
  int n, m, c, s, g;
  int station[21][101][101];
  int COST[21][20001];
 
  while(cin >> n >> m >> c >> s >> g, n){
    fill_n(**station, 21*101*101, INFTY);
    fill_n(*COST, 21 * 20001, 0);
    for(int i = 0 ; i < 21 ; i++ ){
      for(int j = 0 ; j < 101 ; j++ ) station[i][j][j] = 0;
    }
    for(int i = 0 ; i < m ; i++ ){
      int x, y, d, c;
      cin >> x >> y >> d >> c;
      station[c][x][y] = station[c][y][x] = min( station[c][x][y], d);
    }
 
    //わーしゃる
    for(int i = 1 ; i <= c ; i++ ){
      for(int j = 1 ; j <= n ; j++ ){
        for(int k = 1 ; k <= n ; k++ ){
          for(int l = 1 ; l <= n ; l++ ){
            station[i][k][l] = min( station[i][k][l], station[i][k][j] + station[i][j][l]);
          }
        }
      }
    }
    int p[21];
    for(int i = 1 ; i <= c ; i++ ){
      cin >> p[i];
    }
    int cost[52], dist[52];
    for(int i = 1 ; i <= c ; i++ ){
      fill_n( dist, 52, 0);
      fill_n( cost, 52, 0);
      for(int j = 1 ; j < p[i] ; j++ ){
        cin >> dist[j];
      }
      for(int j = 1 ; j <= p[i] ; j++ ){
        cin >> cost[j];
      }
      int diff = cost[1];
      int pos = 1;
      for(int j = 1 ; j < 20001 ; j++ ){
        if( pos < p[i] && dist[pos] < j) pos++;
        COST[i][j]= COST[i][j-1] + cost[pos];
      }
    }
    int ret[101][101];
    fill_n( *ret, 101 * 101, INFTY);
    for(int i = 1 ; i <= c ; i++ ){
      for(int j = 1 ; j <= n ; j++ ){
        for(int k = 1 ; k <= n ; k++ ){
          if(station[i][j][k] != INFTY) ret[j][k] = min( ret[j][k], COST[i][station[i][j][k]]);
        }
      }
    }
    for(int i = 1 ; i <= n ; i++ ){
      for(int j = 1 ; j <= n ; j++ ){
        for(int k = 1 ; k <= n ; k++ ){
          ret[j][k] = min( ret[j][k], ret[j][i] + ret[i][k]);
        }
      }
    }
 
    if(ret[s][g] == INFTY) cout << -1 << endl;
    else cout << ret[s][g] << endl;
  }
    return(0);
 
}

AOJ0204 UFO Shooting Down Operation

解法


当たり判定を間違えててWA連発してしまった。
レーザーの威力が出ない範囲内で当たるという
こんなケースがあったのが気づかなかった。気づけなかった。

ソース


#include<complex>
#include<algorithm>
#include<vector>
#include<map>
#include<iomanip>
#include<iostream>
#include<queue>
using namespace std;
#define fr first
#define sc second

struct line: public vector< complex<double> >{
  line(){};
  line( const complex<double>& a, const complex<double>& b){
    push_back(a);
    push_back(b);
  }
};
struct circle {
  complex<double> p; double r;
  circle():p(0,0),r(0){};
  circle(const complex<double> &p, double r) : p(p),r(r){}
};

typedef complex < double > P;
typedef line               L;
typedef pair < P, P >      Ls;
typedef vector< P >        G;
typedef vector< P >        Ps;
typedef vector< L >        LLL;
typedef circle             C;
const double EPS = 1e-9;
const double INF = 1e8;

bool   eq(P,P); //点:点 同一判定
double cross(P,P); //外積
double dot(P,P); //内積
int    ccw(P,P,P); //3点の位置関係
bool   parallel(L,L); // 直線//直線
bool   orthogonal(L,L); //直線⊥直線
bool   intersect(L,L); //線分:線分交差
bool   intersect(L,P); //線分:点交差
bool   intersect(Ls,Ls); //直線:直線交差
bool   intersect(Ls,L); //直線:線分交差
bool   intersect(Ls,P); //直線:点交差
int    intersect(C,L); //円:線分交点数
bool   intersect(C,Ls); //円:直線交差
bool   intersect(C,C); //円:円交差
bool   intersect(C,P); //円:点交差
double distance(L,L); //線分:線分の距離
double distance(L,P); //線分:点の距離
double distance(P,P); //点:点の距離
double distance(Ls,P); //直線:点距離
double distance(Ls,Ls); //直線:直線距離
double distance(Ls,L); //直線:線分距離
P      crosspoint(L,L); //線分:線分交点計算
L      crosspoint(C,Ls); //円:直線交点計算
L      crosspoint(C,L); //円:線分交点計算
L      crosspoint(C,C); //円:円交点計算
int    contains(G,P); //図形:点内包判定
double area2(G); //面積
bool   isconvex(G); //凸性判定
Ps     convex(G); //凸包

namespace std {
  bool operator < (const P& a, const P& b) {
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
L llcomb(Ls a){
  L line( a.fr, a.sc);
  return line;
}
Ls llrcomb(L a){
  Ls line( a[0], a[1]);
  return line;
}
bool eq( P a, P b){ //OK
  return abs( a - b) < EPS;
}
double cross( P a,  P b){ //OK
  return imag( conj(a) * b);
}
double dot( P a, P b){ //OK
  return real( conj(a) * b);
}
P projection( L l, P p) { //OK
  double t = dot( p - l[0], l[0] - l[1]) / norm( l[0] - l[1]);
  return l[0] + t * ( l[0] - l[1]);
}
int ccw( P a, P b, P c){  //OK
  b -= a, c -= a;
  if(cross(b,c) > 0)    return +1;  // a → b で 反時計方向におれて c
  if(cross(b,c) < 0)    return -1; // a → b で 時計方向におれて c
  if(dot(b,c) < 0)      return +2;  // c -- a -- b
  if(norm(b) < norm(c)) return -2; // a -- b -- c
                        return 0;  // a -- c -- b
}
bool intersect( L a, L b){ //OK
  return ccw( a[0], a[1], b[0]) * ccw( a[0], a[1], b[1]) <= 0 &&
    ccw( b[0], b[1], a[0]) * ccw( b[0], b[1], a[1]) <= 0;
}
bool intersect( L a, P p){ //OK
   return abs( a[0] - p) + abs( a[1] - p) - abs( a[1] - a[0]) < EPS;
}
bool intersect( Ls l, Ls m) { //OK
  return abs(cross(l.sc-l.fr, m.sc-m.fr)) > EPS ||
         abs(cross(l.sc-l.fr, m.fr-l.fr)) < EPS;
}
bool intersect(Ls l, L s) { //OK
  return cross( l.sc - l.fr, s[0] - l.fr) *
         cross( l.sc - l.fr, s[1] - l.fr) < EPS;
}
bool intersect(Ls l, P p) { //OK
  return abs( cross( l.sc - p, l.fr - p)) < EPS;
}
bool intersect( C c, Ls s){ //OK
  return distance( s, c.p) <= c.r + EPS;
}
bool intersect( C a, C b){ //OK
  return ( norm( a.p - b.p) - ( a.r + b.r) * ( a.r + b.r) < EPS) &&
    ( norm( a.p - b.p) - ( a.r - b.r) * ( a.r - b.r) > -EPS);
}
int intersect( C c, L l){ //OK
  if( norm( projection( l, c.p) - c.p) - c.r * c.r > EPS) return 0;
  const double d1 = abs( c.p - l[0]), d2 = abs( c.p - l[1]);
  if( d1 < c.r + EPS && d2 < c.r + EPS) return 0;
  if( d1 < c.r - EPS && d2 > c.r + EPS
      || d1 > c.r + EPS && d2 < c.r - EPS ) return 1;
  const P h = projection( l, c.p);
  if( dot( l[0] - h, l[1] - h) < 0) return 2;
  return 0;
}
bool intersect( C c, P p){ //OK
  return abs( abs( p - c.p) - c.r ) < EPS;
}
double distance( L s, P p){ //OK
  P r = projection(s, p);
  if ( intersect( s, r)) return abs( r - p);
  return min( abs( s[0] - p), abs( s[1] - p));
}
double distance( L a, L b){ //OK
  if(intersect( a, b)) return 0;
  return min( min( distance( a, b[0]), distance( a, b[1])),
              min( distance( b, a[0]), distance( b, a[1])));
}
double distance( Ls l, P p) { //OK
  return abs(p - projection( llcomb(l), p));
}
double distance( Ls l, Ls m) { //OK
  return intersect( l, m) ? 0 : distance( l, m.fr);
}
double distance( Ls l, L s) { //OK
  if (intersect(l, s)) return 0;
  return min(distance(l, s[0]), distance(l, s[1]));
}
double distance( P a, P b){ //OK
  return abs( a - b);
}
bool parallel( L a, L b){
  return abs( cross( a[1] - a[0], b[1] - b[0])) < EPS;
}
bool orthogonal( L a, L b){
  return dot( a[0] - a[1], b[0] - b[1]) < EPS;
}
#define curr(P,i) P[i]
#define next(P,i) P[(i+1)%P.size()]
#define prev(P, i) P[(i+P.size()-1) % P.size()]
enum { OUT, ON, IN };
int conteins(G Q, P p){ //OK
  bool in = false;
  for(int i = 0 ; i < Q.size() ; i++ ){
    P a = curr(Q,i) - p, b = next(Q,i) - p;
    if(imag(a) > imag(b)) swap(a,b);
    if(imag(a) <= 0 && 0 < imag(b) && cross(a,b) < 0) in = !in;
    if(cross(a,b) == 0 && dot(a,b) <= 0) return ON;
  }
  return in ? IN : OUT;
}
double area2(G p){ //OK
  double A = 0;
  for (int i = 0; i < p.size(); ++i){
    A += cross(curr(p, i), next(p, i));
  }
  return A;
}
bool isconvex(G p) { // OK
  for (int i = 0; i < p.size(); ++i){
    if (ccw(prev(p, i), curr(p, i), next(p, i)) > 0) return false;
  }
  return true;
}
Ps convex(Ps ps) { //n>=3 OK
  int k = 0;
  sort(ps.begin(), ps.end());
  Ps ch(2 * ps.size());
  for (int i = 0; i < ps.size(); ch[k++] = ps[i++]){
    while (k >= 2 and ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
  }
  for (int i = ps.size()-2, t = k+1; i >= 0; ch[k++] = ps[i--]){
    while (k >= t and ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
  }
  ch.resize(k-1);
  return ch;
}
P crosspoint(L l, L m) { //OK
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  return m[0] + B / A * (m[1] - m[0]);
}
L crosspoint( C c, Ls l) { //OK
  const P hp = projection( llcomb(l), c.p), h =  hp - c.p;
  const double d2 = norm(h);
  P v = sqrt( c.r * c.r - d2) * ( l.sc - l.fr) / abs( l.sc - l.fr);
  return L(hp - v, hp + v);
}
L crosspoint( C c, L l) { //OK
  if(intersect(c, l) == 2) return crosspoint(c, llrcomb(l));
  L ret = crosspoint(c, llrcomb(l));
  if(dot(l[0] - ret[0], l[1] - ret[0]) < 0) ret[1] = ret[0];
  else ret[0] = ret[1];
  return ret;
}
L crosspoint(C c1, C c2){ //OK
  double d = abs(c1.p - c2.p);
  double s = (c1.r + c2.r + d) / 2;
  double S = sqrt( s * ( s - c1.r) * ( s - c2.r) * ( s - d));
  double h = 2 * S / d;
  P v = ( c2.p - c1.p) / ( abs( c2.p - c1.p));
  double m = sqrt( c1.r * c1.r - h * h);
  return L( c1.p + m * v + h * v * P(0,1), c1.p + m * v - h * v * P(0,1));
}

typedef pair< C, double > Cv;

int main(){

  int n;
  C c;
  c.p = P(0,0);

  while(cin >> c.r >> n, n){
    vector< Cv > ufo(n);
    for(int i = 0 ; i < n ; i++ ){
      double x, y, r, v;
      cin >> x >> y >> r >> v;
      ufo[i] = Cv( C( P( x, y), r), v);
    }

    int cnt = 0;
    while(!ufo.empty()){

      vector<Cv>::iterator mpos;
      double mini = INF;
      for(vector<Cv>::iterator it = ufo.begin() ; it != ufo.end() ; it++){
        double t =  abs((*it).fr.p) / (*it).sc;
        if( t >= 1.0 ) (*it).fr.p -= (*it).fr.p/abs((*it).fr.p) * (*it).sc;
        else (*it).fr.p = P(0,0);
        if(abs((*it).fr.p) <= c.r){
          cnt++;
          ufo.erase(it--);
        } else if( mini > abs((*it).fr.p) ){
          mini = abs((*it).fr.p);
          mpos = it;
        }
      }
      if(ufo.empty()) break;

      L l = L( c.p,(*mpos).fr.p * 2000.0);
      for(vector<Cv>::iterator it = ufo.begin() ; it != ufo.end() ; it++ ){
        if(intersect((*it).fr, l)){
          L p = crosspoint((*it).fr, l);
          if(abs(p[0]) > c.r || abs(p[1]) > c.r){ //あらら
            ufo.erase(it--);
          }
        }
      }
    }
    cout << cnt << endl;
  }
}