Problem:
Web 0.5
In a forest, there lived a spider named Tim. Tim was so smart that he created a huge, well-structured web.
Surprisingly, his web forms a set of equilateral and concentric
N
-sided polygons whose edge lengths
form an arithmetic sequence.
Figure 1: An example web of Tim
Corresponding vertices of the N-sided polygons lie on a straight line, each apart from neighboring ver-
tices by distance 1. Neighboring vertices are connected by a thread (shown in the figure as solid lines),
on which Tim can walk (you may regard Tim as a point). Radial axes are numbered from 1 to
N
in a
rotational order, so you can denote by (
r
,
i
) the vertex on axis
i
and apart from the center of the web by
distance
r
. You may consider the web as infinitely large, i.e. consisting of infinite number of
N
-sided
polygons, since the web is so gigantic.
Tim’s web is thus marvelous, but currently has one problem: due to rainstorms, some of the threads are
damaged and Tim can’t walk on those parts.
Now, a bug has been caught on the web. Thanks to the web having so organized a structure, Tim accu-
rately figures out where the bug is, and heads out for that position. You, as a biologist, are interested in
whether Tim is smart enough to move through the shortest possible route. To judge that, however, you
need to know the length of the shortest route yourself, and thereby decided to write a program which
calculates that length.
Input
The input consists of multiple test cases. Each test case begins with a line containing two integers
N
(3 ≤
N
≤ 100) and
X
(0 ≤
X
≤ 100), where
N
is as described above and
X
denotes the number of
damaged threads. Next line contains four integers
r
S
,
i
S
,
r
T
, and
i
T
, meaning that Tim is starting at (
r
S
,
i
S
) and the bug is at (
r
T
,
i
T
). This line is followed by
X
lines, each containing four integers
r
A
,
i
A
,
r
B
, and
i
B
, meaning that a thread connecting (
r
A
,
i
A
) and (
r
B
,
i
B
) is damaged. Here (
r
A
,
i
A
) and (
r
B
,
i
B
) will be
always neighboring to each other. Also, for all vertices (
r
,
i
) given above, you may assume 1 ≤
r
≤ 10
7
and 1 ≤
i
≤
N
.
There will be at most 200 test cases. You may also assume that Tim is always able to reach where the
bug is.
The input is terminated by a line containing two zeros.
Output
For each test case, print the length of the shortest route in a line. You may print any number of digits
after the decimal point, but the error must not be greater than 0.01.
Sample Input
5 1
2 1 3 2
2 1 2 2
0 0
Output for the Sample Input
4.18

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 605

int N,X;

struct Info{
	Info(int arg_from_dist,int arg_from_line,int arg_to_dist,int arg_to_line){
		from_dist = arg_from_dist;
		from_line = arg_from_line;
		to_dist = arg_to_dist;
		to_line = arg_to_line;
	}
	int from_dist,from_line,to_dist,to_line;
};

struct Info2{
	Info2(int arg_to_index,int arg_to_line){
		to_index = arg_to_index;
		to_line = arg_to_line;
	}
	int to_index,to_line;
};

struct Edge{
	Edge(int arg_to_index,int arg_to_line,double arg_cost){
		to_index = arg_to_index;
		to_line = arg_to_line;
		cost = arg_cost;
	}
	int to_index,to_line;
	double cost;
};

struct State{
	State(int arg_layer_index,int arg_line,double arg_sum_dist){
		layer_index = arg_layer_index;
		line = arg_line;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct State &arg) const{

		return sum_dist > arg.sum_dist; //総距離の昇順
	}

	int layer_index,line;
	double sum_dist;
};

int dist_table[SIZE];
int start_dist,start_line;
int goal_dist,goal_line;
map<int,int> MAP;
vector<int> V;
double min_dist[SIZE][105];
vector<Edge> G[SIZE][105];
vector<Info> info;
vector<Info2> INFO[SIZE][105];


//前後のレイヤを追加
void add_dist(int dist){

	V.push_back(dist+1);
	if(dist > 1){
		V.push_back(dist-1);
	}
}


void func(){

	for(int i = 0; i < SIZE; i++){
		for(int k = 0; k < N; k++){
			G[i][k].clear();
			INFO[i][k].clear();
		}
	}
	MAP.clear();
	V.clear();
	info.clear();

	V.push_back(1); //★★一番内側★★

	scanf("%d %d",&start_dist,&start_line);
	start_line--;
	scanf("%d %d",&goal_dist,&goal_line);
	goal_line--;

	V.push_back(start_dist);
	add_dist(start_dist);

	V.push_back(goal_dist);
	add_dist(goal_dist);

	int dist1,line1,dist2,line2;

	for(int i = 0; i < X; i++){

		scanf("%d %d %d %d",&dist1,&line1,&dist2,&line2);
		line1--;
		line2--;

		info.push_back(Info(dist1,line1,dist2,line2));

		if(dist1 == dist2){ //横

			V.push_back(dist1);
			add_dist(dist1);

		}else{ //縦

			V.push_back(dist1);
			add_dist(dist1);

			V.push_back(dist2);
			add_dist(dist2);
		}
	}

	sort(V.begin(),V.end());
	V.erase(unique(V.begin(),V.end()),V.end());

	int num_layer = 0;
	int index;

	for(int i = 0; i < V.size(); i++){

		MAP[V[i]] = num_layer;
		dist_table[num_layer++] = V[i];
	}

	//infoの仕分け
	for(int i = 0; i < info.size(); i++){

		int from_index = MAP[info[i].from_dist];
		int to_index = MAP[info[i].to_dist];
		INFO[from_index][info[i].from_line].push_back(Info2(to_index,info[i].to_line));
		INFO[to_index][info[i].to_line].push_back(Info2(from_index,info[i].from_line));
	}


	int start_index = -1,goal_index = -1;
	for(int i = 0; i < num_layer; i++){
		if(dist_table[i] == start_dist){

			start_index = i;
		}
		if(dist_table[i] == goal_dist){

			goal_index = i;
		}
	}

	double center_rad = 2*M_PI/(double)N; //多角形の中心角

	//隣接するノードにのみエッジを張る
	for(int i = 0; i < num_layer; i++){

		double a = dist_table[i];
		double len = sqrt(2*a*a-2*a*a*cos(center_rad));

		int tmp_dist = dist_table[i];

		//同レイヤ
		for(int k = 0; k < N; k++){

			int from = k;
			int to = (k+1)%N;

			bool FLG = true;

			for(int p = 0; p < INFO[i][from].size(); p++){
				if(INFO[i][from][p].to_index == i && INFO[i][from][p].to_line == to){

					FLG = false;
					break;
				}
			}
			if(!FLG)continue;

			G[i][from].push_back(Edge(i,to,len));
			G[i][to].push_back(Edge(i,from,len));
		}

		if(i == num_layer-1)continue;

		//次のレイヤと
		for(int k = 0; k < N; k++){

			bool FLG = true;

			for(int p = 0; p < INFO[i][k].size(); p++){
				if(INFO[i][k][p].to_index == i+1 && INFO[i][k][p].to_line == k){

					FLG = false;
					break;
				}
			}
			if(!FLG)continue;

			int diff = dist_table[i+1]-dist_table[i];

			G[i][k].push_back(Edge(i+1,k,diff));
			G[i+1][k].push_back(Edge(i,k,diff));
		}
	}

	for(int i = 0; i < num_layer; i++){
		for(int k = 0; k < N; k++){

			min_dist[i][k] = BIG_NUM;
		}
	}

	priority_queue<State> Q;
	min_dist[start_index][start_line] = 0;
	Q.push(State(start_index,start_line,0));


	int next_index,next_line;
	double next_cost;

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().layer_index][Q.top().line]+EPS){

			Q.pop();

		}else if(Q.top().layer_index == goal_index && Q.top().line == goal_line){

			printf("%.10lf\n",Q.top().sum_dist);
			return;

		}else{

			for(int i = 0; i < G[Q.top().layer_index][Q.top().line].size(); i++){

				next_index = G[Q.top().layer_index][Q.top().line][i].to_index;
				next_line = G[Q.top().layer_index][Q.top().line][i].to_line;
				next_cost = Q.top().sum_dist+ G[Q.top().layer_index][Q.top().line][i].cost;

				if(min_dist[next_index][next_line] > next_cost+EPS){

					min_dist[next_index][next_line] = next_cost+EPS;
					Q.push(State(next_index,next_line,next_cost));
				}
			}
			Q.pop();
		}
	}
}

int main(){

	while(true){

		scanf("%d %d",&N,&X);
		if(N == 0 && X == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 9564
final_rank: 7

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <utility>
#include <queue>
using namespace std;
const double EPS = 1e-10;
const double INF = 1e12;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()
typedef complex<double> P;

struct Pos{
    int r,i;
    Pos(int r, int i):r(r),i(i){}
    Pos(){}
    bool operator<(const Pos &a) const{
        return (r!=a.r)? r<a.r: i<a.i;
    }
    bool operator==(const Pos &a) const{
        return r==a.r && i==a.i;
    }
};

P convert(const Pos &pos, int n){
    double angle = 2*PI*pos.i/n;
    return P(pos.r, 0) *P(cos(angle), sin(angle));
}

int main(){
    while(1){
        int n,x;
        cin >> n >> x;
        if(n==0) break;

        Pos s,t;
        cin >> s.r >> s.i >> t.r >> t.i;
        s.i--; t.i--;
        set<pair<Pos, Pos> > ng;
        for(int i=0; i<x; i++){
            int rs,is,rt,it;
            cin >> rs >> is >> rt >> it;
            is--; it--;
            pair<Pos, Pos> edge(Pos(rs, is), Pos(rt, it));
            if(edge.second < edge.first){
                swap(edge.first, edge.second);
            }
            ng.insert(edge);
        }

        vector<int> rlist;
        rlist.push_back(s.r);
        rlist.push_back(t.r);
        rlist.push_back(1);
        for(const pair<Pos, Pos> &e: ng){
            rlist.push_back(e.first.r);
            rlist.push_back(e.second.r);
        }
        for(int i=rlist.size()-1; i>=0; i--){
            rlist.push_back(rlist[i]-1);
            rlist.push_back(rlist[i]+1);
        }
        sort(rlist.begin(), rlist.end());
        rlist.erase(unique(rlist.begin(), rlist.end()), rlist.end());
        rlist.erase(rlist.begin());
        rlist.push_back(1e8);

        map<Pos, vector<pair<Pos, double> > > adj;
        for(int i=0; i<(int)rlist.size()-1; i++){
            for(int j=0; j<n; j++){
                Pos curr(rlist[i], j);
                Pos next[2];
                next[0] = Pos(rlist[i], (j+1)%n);
                next[1] = Pos(rlist[i+1], j);
                for(int d=0; d<2; d++){
                    pair<Pos, Pos> edge(curr, next[d]);
                    if(edge.second < edge.first) swap(edge.first, edge.second);
                    if(ng.find(edge) == ng.end()){
                        double dist = abs(convert(curr, n) -convert(next[d], n));
                        adj[curr].emplace_back(next[d], dist);
                        adj[next[d]].emplace_back(curr, dist);
                    }
                }
            }
        }

        priority_queue<pair<double, Pos> > wait;
        wait.push(make_pair(0, s));
        map<Pos, double> mincost;
        for(const auto &key: adj){
            mincost[key.first] = INF;
        }
        mincost[s] = 0;
        while(!wait.empty()){
            double dist = -wait.top().first;
            Pos pos = wait.top().second;
            wait.pop();
            if(dist > mincost[pos] +EPS) continue;
            if(pos == t) break;
            for(const auto &next: adj[pos]){
                double ndist = dist +next.second;
                Pos npos = next.first;
                if(ndist +EPS < mincost[npos]){
                    mincost[npos] = ndist;
                    wait.push(make_pair(-ndist, npos));
                }
            }
        }
        cout << fixed << setprecision(5);
        cout << mincost[t] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 9932
final_rank: 8

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define int long long
#define all(v) begin(v), end(v)
#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define reps(i, s, n) for(int i = (int)(s); i < (int)(n); i++)

template<class T1, class T2> void chmin(T1 &a, T2 b){if(a>b)a=b;}
template<class T1, class T2> void chmax(T1 &a, T2 b){if(a<b)a=b;}

using pint = pair<int, int>;
using tint = tuple<int, int, int>;
using vint = vector<int>;

const int inf = 1LL << 55;
const int mod = 1e9 + 7;

int N, X;
int sr, sc, tr, tc;
int ar[101], ac[101];
int br[101], bc[101];
vint R; // compress
map<int, int> mp; // uncompress
set< pair<pint, pint> > st; // non-exist edge

double base;

double distance(int ar, int br) {
  return (ar == br ? (R[ar]+1)*base : abs(R[ar] - R[br]));
}

double mincost[808][101];

using State = tuple<double, int, int>;

const int dr[] = {0, 1, 0, -1};
const int dc[] = {1, 0, -1, 0};

double dijkstra() {
  priority_queue<State, vector<State>, greater<State> > que;
  fill(mincost[0], mincost[808], DBL_MAX/2);
  que.emplace(0, sr, sc);
  mincost[sr][sc] = 0;
  while(!que.empty()) {
    double cost; int r, c;
    tie(cost, r, c) = que.top(); que.pop();
    if(mincost[r][c] < cost) continue;
    if(r == tr && c == tc) return cost;
    rep(i, 4) {
      int nr = r + dr[i], nc = (c+dc[i]+N)%N;
      if(nr < 0 || R.size() <= nr) continue;
      auto u = make_pair(r, c);
      auto v = make_pair(nr, nc);
      if(st.count(make_pair(u, v))) continue;
      double dist = cost + distance(r, nr);
      if(dist < mincost[nr][nc]) {
	mincost[nr][nc] = dist;
	que.emplace(dist, nr, nc);
      }
    }
  }
  return -1;
}

signed main()
{
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  while(cin >> N >> X, N) {
    cin >> sr >> sc >> tr >> tc;
    --sr, --sc, --tr, --tc;
    R.clear();
    R.push_back(0);
    R.push_back(sr);
    R.push_back(tr);
    rep(i, X) {
      cin >> ar[i] >> ac[i] >> br[i] >> bc[i];
      --ar[i], --ac[i], --br[i], --bc[i];
      if(ar[i]) R.push_back(ar[i]-1);
      R.push_back(ar[i]);
      R.push_back(ar[i]+1);
      if(br[i]) R.push_back(br[i]-1);
      R.push_back(br[i]);
      R.push_back(br[i]+1);
    }
    sort(all(R));
    R.erase(unique(all(R)), R.end());
    mp.clear();
    st.clear();
    rep(i, R.size()) mp[R[i]] = i;
    sr = mp[sr], tr = mp[tr];
    rep(i, X) {
      ar[i] = mp[ar[i]], br[i] = mp[br[i]];
      auto u = make_pair(ar[i], ac[i]);
      auto v = make_pair(br[i], bc[i]);
      st.emplace(u, v);
      st.emplace(v, u);
    }
    base = sqrt(2.0-2.0*cos(2.0*acos(-1)/(double)N));
    cout << dijkstra() << endl;
  }

  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 4364
final_rank: 5

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <cmath>
#include <cstdio>
using namespace std;
  
const int MAXH = 400;
const int MAXW = 105;
const int MAXX = 101;
const double inf = 1e100;
const int di[] = {0,1,0,-1};
const int dj[] = {1,0,-1,0};
  
int N, X;
int si, sj, ti, tj;
int pi[MAXX], pj[MAXX], qi[MAXX], qj[MAXX];
vector<int> vi;
map<int,int> mi, rmi;
int H;
set<pair<pair<int,int>, pair<int,int> > > wall;
double x;
  
struct State {
  int pi, pj;
  double cost;
  bool operator < (const State &s) const {
    return cost > s.cost;
  }
};
double cost[MAXH][MAXW];
  
double getDist(int si, int sj, int ti, int tj) {
  if(si == ti) {
    return rmi[si] * x;
  } else {
    return abs(rmi[si]-rmi[ti]);
  }
}
  
double dijkstra(int si, int sj, int ti, int tj) {
  priority_queue<State> que;
  fill(cost[0], cost[MAXH], inf);
  que.push((State){si,sj,0.0});
  cost[si][sj] = 0.0;
  while(!que.empty()) {
    const State s = que.top();
    que.pop();
    if(cost[s.pi][s.pj] < s.cost) continue;
    if(s.pi == ti && s.pj == tj) return s.cost;
    for(int k = 0; k < 4; ++k) {
      State t = s;
      t.pi += di[k];
      t.pj = (t.pj + dj[k] + N) % N;
      if(t.pi >= H) continue;
      if(t.pi < 0) continue;
      if(wall.count(make_pair(make_pair(s.pi,s.pj),make_pair(t.pi,t.pj)))) continue;
      t.cost += getDist(s.pi, s.pj, t.pi, t.pj);
      if(cost[t.pi][t.pj] <= t.cost) continue;
      que.push(t);
      cost[t.pi][t.pj] = t.cost;
    }
  }
  return inf;
}
  
int main() {
  while(cin >> N >> X && (N|X)) {
    cin >> si >> sj >> ti >> tj;
    --sj; --tj;
    for(int i = 0; i < X; ++i) {
      cin >> pi[i] >> pj[i] >> qi[i] >> qj[i];
      --pj[i]; --qj[i];
    }

    vi.clear();
    vi.push_back(1);
    vi.push_back(si);
    vi.push_back(ti);
    for(int i = 0; i < X; ++i) {
      if(pi[i]-1 >= 1) vi.push_back(pi[i]-1);
      vi.push_back(pi[i]);
      vi.push_back(pi[i]+1);
      if(qi[i]-1 >= 1) vi.push_back(qi[i]-1);
      vi.push_back(qi[i]);
      vi.push_back(qi[i]+1);
    }
    sort(vi.begin(), vi.end());
    vi.erase(unique(vi.begin(), vi.end()), vi.end());
  
    mi.clear();
    rmi.clear();
    for(int i = 0; i < vi.size(); ++i) {
      mi[vi[i]] = i;
      rmi[i] = vi[i];
    }
  
    H = vi.size();
    si = mi[si];
    ti = mi[ti];
    for(int i = 0; i < X; ++i) {
      pi[i] = mi[pi[i]];
      qi[i] = mi[qi[i]];
    }
  
    wall.clear();
    for(int i = 0; i < X; ++i) {
      pair<pair<int,int>, pair<int,int> > p = make_pair(make_pair(pi[i],pj[i]),make_pair(qi[i],qj[i]));
      wall.insert(p);
      swap(p.first, p.second);
      wall.insert(p);
    }
  
    x = sqrt(2.0 - 2.0*cos(M_PI*2.0/(double)N));
  
    printf("%.2f\n", dijkstra(si, sj, ti, tj));
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 1704
final_rank: 4

code_snippet: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
typedef pair<int, int> P;
typedef pair<P, P> S;
typedef pair<double, P> state;

int main(){
  int N, X;
  while(cin>>N>>X && N){
    set<int> r_set;
    r_set.insert(1); r_set.insert(2);
    set<S> damage;
    int sr, sp, gr, gp;
    cin>>sr>>sp>>gr>>gp;
    sp--; gp--;
    r_set.insert(sr);
    r_set.insert(gr);
    REP(i, X){
      int r1, p1, r2, p2;
      cin>>r1>>p1>>r2>>p2;
      p1--; p2--;
      damage.insert(S(P(r1, p1), P(r2, p2)));
      damage.insert(S(P(r2, p2), P(r1, p1)));
      r_set.insert(r1);
      r_set.insert(r2);
      r_set.insert(r1 + 1);
      r_set.insert(r2 + 1);
      if(r1 >= 2) r_set.insert(r1 - 1);
      else r_set.insert(2);
      if(r2 >= 2) r_set.insert(r2 - 1);
      else r_set.insert(2);
    }
    vector<int> rs(r_set.begin(), r_set.end());
    int R = rs.size();
    //double dist[1000][100] = {};
    //REP(i, R)REP(j, N) dist[i][j] = 1e16;
    bool dist[1000][100] = {};
    int s_ridx = lower_bound(rs.begin(), rs.end(), sr) - rs.begin();
    priority_queue<state, vector<state>, greater<state> > que;
    que.push(state(0, P(s_ridx, sp)));
    while(!que.empty()){
      state s = que.top(); que.pop();
      int r_idx = s.second.first;
      int p = s.second.second;
      double d = s.first;
      //printf("(rs[%d]=%d, %d) = %lf\n", r_idx, rs[r_idx], p, d);
      if(rs[r_idx] == gr && p == gp){
        printf("%.2lf\n", d);
        break;
      }
      //if(dist[r_idx][p] < d) continue;
      if(dist[r_idx][p]) continue; dist[r_idx][p] = true;
      REP(r, 4){
        if(r % 2){
          int nr_idx = r_idx + r - 2;
          double nd = d + abs(rs[nr_idx] - rs[r_idx]);
          /*
          if(nr_idx >= 0 && nr_idx < R && dist[nr_idx][p] > nd && !damage.count(S(P(rs[r_idx], p), P(rs[nr_idx], p)))){
          */
          if(nr_idx >= 0 && nr_idx < R && !dist[nr_idx][p] && !damage.count(S(P(rs[r_idx], p), P(rs[nr_idx], p)))){
            //dist[r_idx][np] = nd;
            que.push(state(nd, P(nr_idx, p)));
          }
        }else{
          int np = (p + r - 1 + N) % N;
          double nd = (double)d + 2.0 * rs[r_idx] * sin(M_PI/N);
          /*
          if(dist[r_idx][np] > nd && !damage.count(S(P(rs[r_idx], p), P(rs[r_idx], np)))){
          */
          if(!dist[r_idx][np] && !damage.count(S(P(rs[r_idx], p), P(rs[r_idx], np)))){
            //dist[r_idx][np] = nd;
            que.push(state(nd, P(r_idx, np)));
          }
        }
      }
    }
  }

  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1420
final_rank: 1

code_snippet: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
typedef pair<int, int> P;
typedef pair<P, P> S;
typedef pair<double, P> state;

int main(){
  int N, X;
  while(cin>>N>>X && N){
    set<int> r_set;
    r_set.insert(1); r_set.insert(2);
    set<S> damage;
    int sr, sp, gr, gp;
    cin>>sr>>sp>>gr>>gp;
    sp--; gp--;
    r_set.insert(sr);
    r_set.insert(gr);
    r_set.insert(sr + 1);
    r_set.insert(gr + 1);
    if(sr != 1) r_set.insert(sr);
    if(gr != 1) r_set.insert(gr);
    REP(i, X){
      int r1, p1, r2, p2;
      cin>>r1>>p1>>r2>>p2;
      p1--; p2--;
      damage.insert(S(P(r1, p1), P(r2, p2)));
      damage.insert(S(P(r2, p2), P(r1, p1)));
      r_set.insert(r1);
      r_set.insert(r2);
      r_set.insert(r1 + 1);
      r_set.insert(r2 + 1);
      if(r1 >= 2) r_set.insert(r1 - 1);
      else r_set.insert(2);
      if(r2 >= 2) r_set.insert(r2 - 1);
      else r_set.insert(2);
    }
    vector<int> rs(r_set.begin(), r_set.end());
    int R = rs.size();
    //double dist[1000][100] = {};
    //REP(i, R)REP(j, N) dist[i][j] = 1e16;
    bool dist[1000][100] = {};
    int s_ridx = lower_bound(rs.begin(), rs.end(), sr) - rs.begin();
    priority_queue<state, vector<state>, greater<state> > que;
    que.push(state(0, P(s_ridx, sp)));
    while(!que.empty()){
      state s = que.top(); que.pop();
      int r_idx = s.second.first;
      int p = s.second.second;
      double d = s.first;
      //printf("(rs[%d]=%d, %d) = %lf\n", r_idx, rs[r_idx], p, d);
      if(rs[r_idx] == gr && p == gp){
        printf("%.2lf\n", d);
        break;
      }
      //if(dist[r_idx][p] < d) continue;
      if(dist[r_idx][p]) continue; dist[r_idx][p] = true;
      REP(r, 4){
        if(r % 2){
          int nr_idx = r_idx + r - 2;
          double nd = d + abs(rs[nr_idx] - rs[r_idx]);
          /*
          if(nr_idx >= 0 && nr_idx < R && dist[nr_idx][p] > nd && !damage.count(S(P(rs[r_idx], p), P(rs[nr_idx], p)))){
          */
          if(nr_idx >= 0 && nr_idx < R && !dist[nr_idx][p] && !damage.count(S(P(rs[r_idx], p), P(rs[nr_idx], p)))){
            //dist[r_idx][np] = nd;
            que.push(state(nd, P(nr_idx, p)));
          }
        }else{
          int np = (p + r - 1 + N) % N;
          double nd = (double)d + 2.0 * rs[r_idx] * sin(M_PI/N);
          /*
          if(dist[r_idx][np] > nd && !damage.count(S(P(rs[r_idx], p), P(rs[r_idx], np)))){
          */
          if(!dist[r_idx][np] && !damage.count(S(P(rs[r_idx], p), P(rs[r_idx], np)))){
            //dist[r_idx][np] = nd;
            que.push(state(nd, P(r_idx, np)));
          }
        }
      }
    }
  }

  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1420
final_rank: 2

code_snippet: #include<cmath>
#include<queue>
#include<cstdio>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const double INF=1e77;
const double PI=acos(-1);

struct point{
	int r,i;
	bool operator==(const point &p)const{ return r==p.r && i==p.i; }
};

struct edge{ int v; double cost; };

int main(){
	for(int n,m;scanf("%d%d",&n,&m),n||m;){
		const double COST=2*sin(PI/n); // 正 n 角形の一辺の長さ

		point s,t;
		scanf("%d%d%d%d",&s.r,&s.i,&t.r,&t.i); s.i--; t.i--;
		point bad[100][2];
		rep(i,m) rep(j,2) scanf("%d%d",&bad[i][j].r,&bad[i][j].i), bad[i][j].i--;

		vector<int> R; // 候補となる頂点の r の値
		R.push_back(1);
		R.push_back(s.r);
		R.push_back(t.r);
		rep(i,m) rep(j,2) {
			R.push_back(bad[i][j].r);
			R.push_back(bad[i][j].r+1);
			R.push_back(max(bad[i][j].r-1,1));
		}
		sort(R.begin(),R.end());
		R.erase(unique(R.begin(),R.end()),R.end());

		int N=n*R.size();
		static vector<edge> G[60300];
		rep(u,N) G[u].clear();
		rep(i,R.size()){
			int r=R[i];
			rep(j,n){
				// 左
				bool ok=true;
				rep(k,m){
					if(bad[k][0]==(point){r,j} && bad[k][1]==(point){r,(j-1+n)%n}
					|| bad[k][1]==(point){r,j} && bad[k][0]==(point){r,(j-1+n)%n}) ok=false;
				}
				if(ok){
					int u=n*i+j,v=n*i+(j-1+n)%n;
					G[u].push_back((edge){v,r*COST});
					G[v].push_back((edge){u,r*COST});
				}

				// 上
				if(i+1<R.size()){
					ok=true;
					int r2=R[i+1];
					rep(k,m){
						if(bad[k][0]==(point){r,j} && bad[k][1]==(point){r2,j}
						|| bad[k][1]==(point){r,j} && bad[k][0]==(point){r2,j}) ok=false;
					}
					if(ok){
						int u=n*i+j,v=n*(i+1)+j;
						G[u].push_back((edge){v,r2-r});
						G[v].push_back((edge){u,r2-r});
					}
				}
			}
		}

		// Dijkstra
		int s_id=n*(find(R.begin(),R.end(),s.r)-R.begin())+s.i;
		int t_id=n*(find(R.begin(),R.end(),t.r)-R.begin())+t.i;
		static double d[60300];
		rep(u,N){
			d[u]=(u==s_id?0:INF);
		}
		priority_queue< pair<double,int> > Q; Q.push(make_pair(0,s_id));
		while(!Q.empty()){
			double d_now=-Q.top().first;
			int u=Q.top().second; Q.pop();

			if(d_now>d[u]) continue;

			rep(i,G[u].size()){
				edge e=G[u][i];
				if(d[e.v]>d[u]+e.cost){
					d[e.v]=d[u]+e.cost;
					Q.push(make_pair(-d[e.v],e.v));
				}
			}
		}

		printf("%.9f\n",d[t_id]);
	}

	return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 5068
final_rank: 6

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

const double PI = acos(-1.0);
const double EPS = 1.0e-10;
const double INF = DBL_MAX / 1000;

int main()
{
    int _tmp = 0;

    for(;;){
        int n, x;
        cin >> n >> x;
        if(n == 0)
            return 0;

        int rStart, iStart, rGoal, iGoal;
        cin >> rStart >> iStart >> rGoal >> iGoal;
        
        vector<int> r1(x), i1(x), r2(x), i2(x);
        for(int j=0; j<x; ++j)
            cin >> r1[j] >> i1[j] >> r2[j] >> i2[j];

        // スタート、ゴール、失われた辺が位置する多角形と、その前後の多角形のみに注目
        // また、一番中央にある多角形にも注目する
        map<int, int> rIndex;
        rIndex[1];
        for(int j=0; j<3; ++j){
            rIndex[rStart - 1 + j];
            rIndex[rGoal - 1 + j];
        }
        for(int j=0; j<x; ++j){
            for(int k=0; k<3; ++k){
                rIndex[r1[j] - 1 + k];
                rIndex[r2[j] - 1 + k];
            }
        }
        if(rIndex.begin()->first == 0)
            rIndex.erase(rIndex.begin());

        int m = 0;        // 注目する多角形の数
        vector<int> rPos; // 注目する多角形の位置
        for(map<int, int>::iterator it=rIndex.begin(); it!=rIndex.end(); ++it){
            it->second = m;
            ++ m;
            rPos.push_back(it->first);
        }

        set<pair<pair<int, int>, pair<int, int> > > damage;
        for(int j=0; j<x; ++j){
            damage.insert(make_pair(make_pair(rIndex[r1[j]], i1[j]), make_pair(rIndex[r2[j]], i2[j])));
            damage.insert(make_pair(make_pair(rIndex[r2[j]], i2[j]), make_pair(rIndex[r1[j]], i1[j])));
        }

        vector<vector<double> > minDist(m, vector<double>(n+1, INF));
        minDist[rIndex[rStart]][iStart] = 0.0;
        multimap<double, pair<int, int> > mm;
        mm.insert(make_pair(0.0, make_pair(rIndex[rStart], iStart)));

        for(;;){
            double dist0 = mm.begin()->first;
            int r0 = mm.begin()->second.first;
            int i0 = mm.begin()->second.second;
            mm.erase(mm.begin());
            if(dist0 > minDist[r0][i0] + EPS)
                continue;

            if(r0 == rIndex[rGoal] && i0 == iGoal){
                printf("%.10f\n", dist0);
                break;
            }

            for(int j=0; j<4; ++j){
                double dist = dist0;
                int r = r0;
                int i = i0;
                if(j % 2 == 0){
                    r = r - 1 + j;
                    if(r == -1 || r == m)
                        continue;
                    dist += abs(rPos[r] - rPos[r0]);
                }else{
                    i = (i - 3 + j + n) % n + 1;
                    dist += rPos[r] * sin(PI / n) * 2.0;
                }

                if(damage.find(make_pair(make_pair(r0, i0), make_pair(r, i))) != damage.end())
                    continue;

                if(dist < minDist[r][i] - EPS){
                    minDist[r][i] = dist;
                    mm.insert(make_pair(dist, make_pair(r, i)));
                }
            }
        }
    }
}
accuracy: 1
time_ms: 30
memory_kb: 1588
final_rank: 3