Problem:
Problem C:
Hexerpents of Hexwamp
Hexwamp is a strange swamp, paved with regular hexagonal dimples.
Hexerpents crawling in this area are serpents adapted to the
environment, consisting of a chain of regular hexagonal sections.  Each
section fits in one dimple.
Hexerpents crawl moving some of their sections from the dimples they
are in to adjacent ones.  To avoid breaking their bodies, sections
that are adjacent to each other before the move should also be
adjacent after the move.  When one section moves, sections adjacent to
it support the move, and thus they cannot move at that time.  Any
number of sections, as far as no two of them are adjacent to each
other, can move at the same time.
You can easily find that a hexerpent can move its sections at its
either end to only up to two dimples, and can move intermediate
sections to only one dimple, if any.
For example, without any obstacles, a hexerpent can crawl forward
twisting its body as shown in Figure C-1, left to right.  In this
figure, the serpent moves four of its eight sections at a time, and
moves its body forward by one dimple unit after four steps of moves.
Actually, they are much better in crawling sideways, like sidewinders.
Figure C-1: Crawling forward
Their skin is so sticky that if two sections of a serpent that are not
originally adjacent come to adjacent dimples (Figure C-2), they will
stick together and the serpent cannot but die.   Two sections cannot
fit in one dimple, of course.  This restricts serpents' moves
further.  Sometimes, they have to make some efforts to get a food
piece even when it is in the dimple next to their head.
Figure C-2: Fatal case
Hexwamp has rocks here and there.  Each rock fits in a dimple.
Hexerpents' skin does not stick to rocks, but they cannot crawl over
the rocks.  Although avoiding dimples with rocks restricts their
moves, they know the geography so well that they can plan the fastest
paths.
You are appointed to take the responsibility of the head of the
scientist team to carry out academic research on this swamp and the
serpents.  You are expected to accomplish the research, but never at
the sacrifice of any casualty.  Your task now is to estimate how soon
a man-eating hexerpent may move its head (the first section) to the
position of a scientist in the swamp.  Their body sections except for
the head are quite harmless and the scientist wearing high-tech
anti-sticking suit can stay in the same dimple with a body section of
the hexerpent.
Input
The input is a sequence of several datasets, and the end of the input
is indicated by a line containing a single zero.  The number of
datasets never exceeds 10.
Each dataset looks like the following.
the number of sections the serpent has
(=
n
)
x
1
y
1
x
2
y
2
...
x
n
y
n
the number of rocks the swamp has (=k)
u
1
v
1
u
2
v
2
...
u
k
v
k
X
Y
The first line of the dataset has an integer
n
that indicates
the number of sections the hexerpent has, which is 2 or greater and
never exceeds 8.  Each of the
n
followi
...(truncated)

Submitted solutions:

code_snippet: // AOJ #1143 Hexerpents of Hexwamp
// 2025.5.12

#include <bits/stdc++.h>
using namespace std;
using pii = pair<int,int>;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0; int c = gc();
	if (c == '-') {	c = gc();
		do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
		return -n;
	}
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(int n) {
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

const pii d[7] = {
    {0,-1},{1,-1},{1,0},{0,1},{-1,1},{-1,0},{0,0}
};

vector<vector<pii>> Body[9];
vector<vector<pii>> g[9];

inline int hexDist(const pii &a, const pii &b){
    int dx = a.first - b.first;
    int dy = a.second - b.second;
    if((dx<0) ^ (dy<0)) return max(abs(dx),abs(dy));
    return abs(dx)+abs(dy);
}

void enumBody(vector<pii> &p){
    int k = p.size();
    Body[k].push_back(p);
    if(k==8) return;
    pii b = p.back();
    p.emplace_back();
    for(int i=0;i<6;i++){
        p.back() = {b.first + d[i].first, b.second + d[i].second};
        bool ok = true;
        for(int j=k-2;j>=0 && ok;j--) if(hexDist(p[j], p.back())<=1) ok = false;
        if(ok) enumBody(p);
    }
    p.pop_back();
}

void makeGraph(){
    for(int k=1;k<=8;k++){
        int N = Body[k].size();
        g[k].assign(N, {});
        for(int i=0;i<N;i++){
            for(int j=0;j<i;j++){
                for(int l=0;l<7;l++){
                    bool ok = true, prev = (l!=6);
                    for(int q=1;q<k && ok;q++){
                        pii pj = Body[k][j][q];
                        pii pi = Body[k][i][q];
                        pii moved = {pi.first - d[l].first, pi.second - d[l].second};
                        int dist = hexDist(pj, moved);
                        if(dist>1 || (dist==1 && prev)) ok = false;
                        prev = (dist == 1);
                    }
                    if(ok){
                        g[k][i].emplace_back(j, l);
                        int rl = (l==6 ? 6 : (l+3)%6);
                        g[k][j].emplace_back(i, rl);
                    }
                }
            }
        }
    }
}

struct St{ int x,y,id,c; };

int main(){
    vector<pii> tmp(1,{0,0});
    enumBody(tmp);
    makeGraph();

    while(true){
        int n = Cin();
        if (n==0) break;

        vector<pii> B(n);
        for(int i=0;i<n;i++) {
            int x = Cin(), y = Cin();
            B[i] = {x, y};
        }

        const int OFF = 30, LIM = 60;
        static bool rock[LIM][LIM];
        static bool vis[LIM][LIM][4200];
        memset(rock,0,sizeof(rock));
        memset(vis,0,sizeof(vis));

        int m = Cin();

        pii head0 = B[0];
        for(int i=0;i<m;i++){
            pii t;
            t.first = Cin(), t.second = Cin();
            int xx = t.first - head0.first + OFF;
            int yy = t.second - head0.second + OFF;
            if(xx>=0&&xx<LIM&&yy>=0&&yy<LIM) rock[xx][yy]=1;
        }

        pii G;
        G.first = Cin(), G.second = Cin();
        G.first = G.first - head0.first + OFF;
        G.second= G.second - head0.second+ OFF;

        for(int i=0;i<n;i++){
            B[i].first  -= head0.first;
            B[i].second -= head0.second;
        }
        int sid = find(Body[n].begin(), Body[n].end(), B) - Body[n].begin();

        queue<St> q;
        q.push({OFF,OFF,sid,0});
        vis[OFF][OFF][sid] = true;
        int ans = 20;

        while(!q.empty()){
            auto s = q.front(); q.pop();
            if(s.x==G.first && s.y==G.second){
                ans = s.c;
                break;
            }
            for(auto &e : g[n][s.id]){
                int nid = e.first, dir = e.second;
                int nx = s.x + d[dir].first;
                int ny = s.y + d[dir].second;
                int nc = s.c + 1;

                if(nc + hexDist({nx,ny}, G) >= 20) continue;
                if(nx<0||nx>=LIM||ny<0||ny>=LIM) continue;
                if(vis[nx][ny][nid]) continue;

                bool ok = true;
                for(auto &seg : Body[n][nid]){
                    int xx = nx + seg.first;
                    int yy = ny + seg.second;
                    if(xx<0||xx>=LIM||yy<0||yy>=LIM||rock[xx][yy]){
                        ok = false;
                        break;
                    }
                }
                if(!ok) continue;
                vis[nx][ny][nid] = true;
                q.push({nx,ny,nid,nc});
            }
        }
        Cout(ans);
    }
    return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 20324
final_rank: 2

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

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int dx[6] = {1,0,-1,-1,0,1}, dy[6] = {0,1,1,0,-1,-1};
map<pair<int,int>,int> moving;
vector<map<int,vector<pair<int,int>>>> mp(9);
vector<map<vector<int>,bool>> mpValid(9);
vector<vector<vector<int>>> masks(9);

int encode(int N, vector<int> V) {
    int Ret = 0;
    rep(i,0,N-1) {
        Ret *= 6;
        Ret += V[i];
    }
    return Ret;
}

vector<int> decode(int N, int E) {
    vector<int> Ret;
    rep(i,0,N-1) {
        Ret.push_back(E % 6);
        E /= 6;
    }
    reverse(ALL(Ret));
    return Ret;
}

bool isValid(int N, vector<int> V) {
    if (mpValid[N].count(V)) return mpValid[N][V];
    vector<pair<int,int>> P(N);
    P[0] = {0,0};
    rep(i,0,N-1) P[i+1] = {P[i].first + dx[V[i]], P[i].second + dy[V[i]]};
    rep(i,0,N) {
        rep(j,i+2,N) {
            if (P[i] == P[j]) return mpValid[N][V] = false;
            if (moving.count({P[j].first-P[i].first, P[j].second-P[i].second})) return mpValid[N][V] = false;
        }
    }
    return mpValid[N][V] = true;
}

void make_move(int N, int E) {
    if (mp[N].count(E)) return;
    auto V = decode(N,E);
    for (vector<int> mask : masks[N]) {
        int headmove = -1;
        auto NV = V;
        if (mask[0] == 0) headmove = (V[0]+5) % 6, NV[0] += 1, NV[0] %= 6;
        if (mask[0] == 2) headmove = (V[0]+1) % 6, NV[0] += 5, NV[0] %= 6;
        rep(i,1,N-1) {
            NV[i-1] += (5+mask[i]);
            NV[i-1] %= 6;
            NV[i] += (7-mask[i]);
            NV[i] %= 6;
        }
        NV[N-2] += (5+mask[N-1]);
        NV[N-2] %= 6;
        if (!isValid(N,NV)) continue;
        mp[N][E].push_back({headmove, encode(N,NV)});
    }
}

int main() {
    rep(i,0,6) moving[{dx[i],dy[i]}] = i;
    rep(i,2,9) {
        rep(j,0,pow(3,i)) {
            vector<int> B(i, 0);
            int J = j;
            rep(k,0,i) B[k] = J % 3, J /= 3;
            bool flag = true;
            rep(k,0,i-1) if (B[k] != 1 && B[k+1] != 1) flag = false;
            if (flag) masks[i].push_back(B);
        }
    }
while(1) {
    int N;
    cin >> N;
    if (N == 0) return 0;
    vector<int> X(N), Y(N);
    rep(i,0,N) cin >> X[i] >> Y[i];
    int SX = X[0], SY = Y[0];
    vector<int> SV(N-1);
    rep(i,0,N-1) SV[i] = moving[{X[i+1]-X[i], Y[i+1]-Y[i]}];
    int SE = encode(N,SV);
    int M;
    cin >> M;
    set<pair<int,int>> cantmove;
    rep(i,0,M) {
        int BX, BY;
        cin >> BX >> BY;
        cantmove.insert({BX,BY});
    }
    int GX, GY;
    cin >> GX >> GY;
    auto canMove = [&](int CX, int CY, int E) -> bool {
        auto V = decode(N,E);
        if (!isValid(N,V)) return false;
        if (cantmove.count({CX,CY})) return false;
        rep(i,0,N-1) {
            CX += dx[V[i]], CY += dy[V[i]];
            if (cantmove.count({CX,CY})) return false;
        }
        return true;
    };
    map<tuple<int,int,int>,int> memo;
    int ANS = 20;
    auto DFS = [&](auto self, int CX, int CY, int E, int cnt) -> void {
        if (memo.count({CX,CY,E}) && memo[{CX,CY,E}] <= cnt) return;
        memo[{CX,CY,E}] = cnt;
        if (cnt + (abs(CX-GX)+abs(CY-GY)) / 2 >= ANS) return;
        if (CX == GX && CY == GY) {
            chmin(ANS, cnt);
            return;
        }
        make_move(N,E);
        for (auto Next : mp[N][E]) {
            int NX = CX, NY = CY;
            if (Next.first >= 0) NX += dx[Next.first], NY += dy[Next.first];
            int NE = Next.second;
            if (!canMove(NX,NY,NE)) continue;
            self(self,NX,NY,NE,cnt+1);
        }
        return;
    };
    DFS(DFS,SX,SY,SE,0);
    cout << ANS << endl;
}
}
accuracy: 1
time_ms: 10850
memory_kb: 35792
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pi;
typedef vector<ll> vi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define ALL(A) A.begin(),A.end()
int main(){
    while(1){
        ll N;cin>>N;
        if(!N)return 0;
        vector<pi>snake(N);
        REP(i,N)cin>>snake[i].first>>snake[i].second;
        ll K;cin>>K;
        vector<pi>swamp(K);
        REP(i,K)cin>>swamp[i].first>>swamp[i].second;
        sort(ALL(swamp));
        ll X,Y;cin>>X>>Y;
        ll ans=20;
        map<vector<pi>,ll>D;
        D[snake]=0;
        queue<vector<pi>>Q;
        Q.emplace(snake);
        vector<pi>move={
            pi(-1,0),pi(-1,1),pi(0,1),pi(0,-1),pi(1,0),pi(1,-1)
        };
        auto valid=[&](vector<pi>&nec){
            REP(i,N-1){
                ll x=nec[i].first-nec[i+1].first;
                ll y=nec[i].second-nec[i+1].second;
                if(max(abs(x),abs(y))>1||x==y)return 0;
            }
            REP(i,N)REP(j,i-1){
                ll x=nec[i].first-nec[j].first;
                ll y=nec[i].second-nec[j].second;
                if(max(abs(x),abs(y))<=1&&x!=y)return 0;
                if(x==0&&y==0)return 0;
            }
            for(auto s:nec)if(binary_search(ALL(swamp),s))return 0;
            return 1;
        };
        auto adj=[](pi a,pi b){
            ll x=a.first-b.first,y=a.second-b.second;
            return abs(x)<2&&abs(y)<2&&x!=y;
        };
        while(!Q.empty()){
            snake=Q.front();Q.pop();
            if(D[snake]>=ans)continue;
            if(snake[0]==pi(X,Y)){
                ans=D[snake];
                continue;
            }
            vector<vector<vector<pi>>>X(N+2);
            X[0]=X[1]={snake};
            REP(i,N){
                vector<vector<pi>>K;
                REP(j,i+1)for(auto s:X[j]){
                    for(auto[dx,dy]:move){
                       s[i].first+=dx;
                       s[i].second+=dy;
                       bool ok=1;
                       if(i&&!adj(s[i],s[i-1]))ok=0;
                       if(i<N-1&&!adj(s[i],s[i+1]))ok=0;
                       if(ok)K.emplace_back(s);
                       s[i].first-=dx;
                       s[i].second-=dy;
                    }
                }
                sort(ALL(K));
                K.erase(unique(ALL(K)),K.end());
                X[i+2]=K;
            }
            for(auto xx:X)for(auto nec:xx)if(valid(nec)){
                if(D.find(nec)==D.end()){
                    D[nec]=D[snake]+1;
                    Q.emplace(nec);
                }
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10550
memory_kb: 64236
final_rank: 20

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

template < class T > vector< T >& operator++(vector< T >& a) { for(T& x : a) x++; return a; }
template < class T > vector< T >& operator--(vector< T >& a) { for(T& x : a) x--; return a; }
template < class T > vector< T >  operator++(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x++; return res; }
template < class T > vector< T >  operator--(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x--; return res; }

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

int dx[] = {-1, -1,  0,  0, +1, +1};
int dy[] = { 0, +1, -1, +1, -1,  0};

int solve(int n) {
    using P = pair<int,int>;
    using D = vector< P >;
    D s(n);
    for(auto &[x, y] : s) x = in(), y = in();
    set< P > b; {
        int k = in();
        for(int _ : rep(k)) {
            int u = in(), v = in();
            b.insert({u, v});
        }
    }
    P T; T.first = in(), T.second = in();

    auto near = [&](const P& a, const P& b) {
        int dx = a.first - b.first, dy = a.second - b.second;
        if(dx == -1) return             dy == 0 or dy == +1;
        if(dx ==  0) return dy == -1 or dy == 0 or dy == +1;
        if(dx == +1) return dy == -1 or dy == 0;
        return false;
    };

    map< D, int > dist;
    queue< pair<int, D> > q;
    q.push({dist[s] = 0, s});

    while(not q.empty()) {
        auto [d, v] = q.front(); q.pop();

        D nv;
        auto dfs = [&](auto self, int i) -> bool {
            if(i == n) {
                bool ok = [&] {
                    for(int a : rep(n)) for(int b : rep(a + 2, n)) {
                        if(near(nv[a], nv[b])) return false;
                    }
                    return true;
                }();
                if(ok) {
                    if(nv[0] == T) return true;
                    if(not dist.count(nv)) q.push({dist[nv] = d + 1, nv});
                }
                return false;
            }

            nv.push_back(v[i]);
            if(self(self, i + 1)) return true;
            nv.pop_back();

            for(int dir : rep(6)) {
                P p = {v[i].first + dx[dir], v[i].second + dy[dir]};
                if(0 <= i - 1 and not near(v[i - 1], p)) continue;
                if(i + 1 <  n and not near(v[i + 1], p)) continue;
                if(b.count(p)) continue;

                if(i + 1 < n) {
                    nv.push_back(p);
                    nv.push_back(v[i + 1]);
                    if(self(self, i + 2)) return true;
                    nv.pop_back();
                    nv.pop_back();
                } else {
                    nv.push_back(p);
                    if(self(self, i + 1)) return true;
                    nv.pop_back();
                }
            }
            return false;
        }; if(dfs(dfs, 0)) return d + 1;
    }
    assert(0);
}

int main() {
    while(true) {
        int n = in(); if(n == 0) return 0;
        print(solve(n));
    }
}
accuracy: 1
time_ms: 3270
memory_kb: 32192
final_rank: 7

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

template < class T > vector< T >& operator++(vector< T >& a) { for(T& x : a) x++; return a; }
template < class T > vector< T >& operator--(vector< T >& a) { for(T& x : a) x--; return a; }
template < class T > vector< T >  operator++(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x++; return res; }
template < class T > vector< T >  operator--(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x--; return res; }

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

int dx[] = {-1, -1,  0,  0, +1, +1};
int dy[] = { 0, +1, -1, +1, -1,  0};

int solve(int n) {
    using P = pair<int,int>;
    using D = vector< P >;
    D s(n);
    for(auto &[x, y] : s) x = in(), y = in();
    set< P > b; {
        int k = in();
        for(int _ : rep(k)) {
            int u = in(), v = in();
            b.insert({u, v});
        }
    }
    pair<int,int> T; T.first = in(), T.second = in();

    auto near = [&](const P& a, const P& b) {
        int dx = a.first - b.first, dy = a.second - b.second;
        if(dx == -1) return             dy == 0 or dy == +1;
        if(dx ==  0) return dy == -1 or dy == 0 or dy == +1;
        if(dx == +1) return dy == -1 or dy == 0;
        return false;
    };

    map< D, int > dist;
    queue< pair<int, D> > q;
    q.push({dist[s] = 0, s});

    while(not q.empty()) {
        auto [d, v] = q.front(); q.pop();

        vector<pair<int,int>> nv;
        auto dfs = [&](auto self, int i) -> bool {
            if(i == n) {
                bool ok = [&] {
                    for(int a : rep(n)) for(int b : rep(a + 2, n)) {
                        if(near(nv[a], nv[b])) return false;
                    }
                    return true;
                }();
                if(ok) {
                    if(nv[0] == T) return true;
                    if(not dist.count(nv)) q.push({dist[nv] = d + 1, nv});
                }
                return false;
            }

            nv.push_back(v[i]);
            if(self(self, i + 1)) return true;
            nv.pop_back();

            for(int dir : rep(6)) {
                P p = {v[i].first + dx[dir], v[i].second + dy[dir]};
                if(0 <= i - 1 and not near(v[i - 1], p)) continue;
                if(i + 1 <  n and not near(v[i + 1], p)) continue;
                if(b.count(p)) continue;

                if(i + 1 < n) {
                    nv.push_back(p);
                    nv.push_back(v[i + 1]);
                    if(self(self, i + 2)) return true;
                    nv.pop_back();
                    nv.pop_back();
                } else {
                    nv.push_back(p);
                    if(self(self, i + 1)) return true;
                    nv.pop_back();
                }
            }
            return false;
        }; if(dfs(dfs, 0)) return d + 1;
    }
    assert(0);
}

int main() {
    while(true) {
        int n = in(); if(n == 0) return 0;
        print(solve(n));
    }
}
accuracy: 1
time_ms: 3290
memory_kb: 32184
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vvvb = vector<vvb>;
#define all(A) A.begin(),A.end()
#define rep(i, n) for (int i = 0; i < (int) (n); i++)
template<class T>
void chmax(T& p, T q) { if (p < q)p = q; };

vll dx={1,1,0,-1,-1,0};
vll dy={-1,0,1,1,0,-1};
using snake=pair<vll,vll>;

//(x,y)と(p,q)は隣接しているか?
bool is_adj(ll x,ll y,ll p,ll q){
    ll u=x-p;
    ll v=y-q;
    if(abs(u)+abs(v)==0)return 0;
    if(abs(u)+abs(v)==1)return 1;
    if(abs(u)+abs(v)==2&&u+v==0)return 1;
    return 0;
}



bool is_adj(snake &S1,snake &S2){
    return 0;
}

//(0,0)が頭の蛇がどう移動できるか? 長さ毎に管理
vector<map<snake,vector<snake>>> canmove(9);

//くねり方. 
//端:0,1,2 その他:0,1 
vector<vector<vector<ll>>> kuneri(9);


//蛇がvalidか?
bool is_valid(vll &X,vll &Y){
    ll N=X.size();
    set<pair<ll,ll>> S;
    rep(i,N){
        if(S.count({X[i],Y[i]}))return 0;
        S.insert({X[i],Y[i]});
    }
    rep(i,N-1){
        if(!is_adj(X[i],Y[i],X[i+1],Y[i+1]))return 0;
        if(i==N-2)return 1;
        if(is_adj(X[i],Y[i],X[i+2],Y[i+2]))return 0;
    }
    return 1;
}

//岩に載るか
bool over_rock(snake &S,set<pair<ll,ll>>&ROCK){
    ll N=S.first.size();
    rep(i,N)if(ROCK.count({S.first[i],S.second[i]}))return 1;
    return 0;
}

//頭が(0,0)なvalidな蛇全列挙
void making_snake(vll &X,vll &Y){
    if(X.size()>=2&&X.size()<=8){
        canmove[X.size()][snake({X,Y})]={};
    }
    if(X.size()==8)return;
    rep(d,6){
        X.push_back(X.back()+dx[d]);
        Y.push_back(Y.back()+dy[d]);
        if(is_valid(X,Y)){
            making_snake(X,Y);
        }
        X.pop_back();
        Y.pop_back();
    }
}

//くねり方全列挙
void making_kuneri(vll &K){
    if(K.size()==0){
        rep(i,3){
            K.push_back(i);
            making_kuneri(K);
            K.pop_back();
        }
    }
    else{
        rep(i,3){
            K.push_back(i);
            kuneri[K.size()].push_back(K);
            K.pop_back();
            if(K.back()!=0)break;
        }
        if(K.size()==7)return;
        rep(i,2){
            K.push_back(i);
            making_kuneri(K);
            K.pop_back();
            if(K.back()!=0)return;
        }
    }
}

//蛇Sのn節目をf移動.(f:1,2)
pair<ll,ll> trans(snake S,ll n,ll f){
    ll sz=S.first.size();
    if(n==0){
        if(f==1){
            ll x=S.first[0];
            ll y=S.second[0];
            rep(d,6){
                ll nx=x+dx[d];
                ll ny=y+dy[d];
                if(is_adj(nx,ny,S.first[1],S.second[1])){
                    return {nx,ny};
                }
            }
        }
        if(f==2){
            ll x=S.first[0];
            ll y=S.second[0];
            for(ll d=5;d>=0;d--){
                ll nx=x+dx[d];
                ll ny=y+dy[d];
                if(is_adj(nx,ny,S.first[1],S.second[1])){
                    return {nx,ny};
                }
            }
        }
    }
    else if(n+1==sz){
        if(f==1){
            ll x=S.first.back();
            ll y=S.second.back();
            rep(d,6){
                ll nx=x+dx[d];
                ll ny=y+dy[d];
                if(is_adj(nx,ny,S.first[sz-2],S.second[sz-2])){
                    return {nx,ny};
                }
            }
        }
        if(f==2){
            ll x=S.first[sz-1];
            ll y=S.second[sz-1];
            for(ll d=5;d>=0;d--){
                ll nx=x+dx[d];
                ll ny=y+dy[d];
                if(is_adj(nx,ny,S.first[sz-2],S.second[sz-2])){
                    return {nx,ny};
                }
            }
        }
    }
    else{
        ll x=S.first[n];
        ll y=S.second[n];
        rep(d,6){
            ll nx=x+dx[d];
            ll ny=y+dy[d];
            if(is_adj(nx,ny,S.first[n-1],S.second[n-1])&&is_adj(nx,ny,S.first[n+1],S.second[n+1])){
                return {nx,ny};
            }
        }
    }
    return {-1,-1};
}

ll ress=0;

//くねる.
void kuneru(){
    rep(sz,9){
        if(sz<2)continue;

        for(auto S:canmove[sz]){
            for(auto K:kuneri[sz]){
                vll NX(sz),NY(sz);
                rep(j,sz){
                    if(K[j]==0){
                        NX[j]=S.first.first[j];
                        NY[j]=S.first.second[j];
                    }
                    else{
                        auto XY=trans(S.first,j,K[j]);
                        NX[j]=XY.first;
                        NY[j]=XY.second;
                    }
                }
                snake NS={NX,NY};
                if(is_valid(NX,NY)){
                    canmove[sz][S.first].push_back(NS);
                }
            }
        }
    }
}

/*
前計算を行う
- (0,0)頭の蛇全列挙
- (0,0)頭の蛇の一手での移動先全列挙(124974ペアある. 長さを8に固定すれば91798通り. 1状態からの最大値は72通り)
*/
void init(){
    vll X={0},Y={0};
    vll K={};
    making_snake(X,Y);
    making_kuneri(K);
    kuneru();
}

void print(snake S){
    ll N=S.first.size();
    rep(i,N)cout<<"("<<S.first[i]<<","<<S.second[i]<<")";
    cout<<endl;
}

void solve(ll N) {
    vll X(N),Y(N);
    rep(i,N)cin>>X[i]>>Y[i];
    ll M;
    cin>>M;
    set<pair<ll,ll>> ROCK;
    rep(i,M){
        ll x,y;
        cin>>x>>y;
        ROCK.insert({x,y});
    }

    ll GX,GY;
    cin>>GX>>GY;
    map<snake,ll> dist;
    dist[{X,Y}]=0;
    queue<snake> Q;
    Q.push({X,Y});

    while(!Q.empty()){
        snake S=Q.front();
        Q.pop();
        snake MS=S;
        rep(i,N){
            MS.first[i]-=S.first[0];
            MS.second[i]-=S.second[0];
        }
        for(snake NS:canmove[N][MS]){
            rep(i,N){
                NS.first[i]+=S.first[0];
                NS.second[i]+=S.second[0];
            }
            if(abs(NS.second[0]-GY)>10||abs(NS.first[0]-GX)>20)continue;
            if(over_rock(NS,ROCK))continue;
            if(!dist.count(NS)){
                if(NS.first[0]==GX&&NS.second[0]==GY){
                    cout<<dist[S]+1<<endl;
                    return;
                }
                dist[NS]=dist[S]+1;
                Q.push(NS);
            }
        }
    }
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    init();

    
    ll N;
    while (cin >> N) {
        if (N == 0)return 0;
        solve(N);
    }

}
accuracy: 1
time_ms: 2970
memory_kb: 77528
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vvvb = vector<vvb>;
#define all(A) A.begin(),A.end()
#define rep(i, n) for (int i = 0; i < (int) (n); i++)
template<class T>
void chmax(T& p, T q) { if (p < q)p = q; };

vll dx={1,1,0,-1,-1,0};
vll dy={-1,0,1,1,0,-1};
using snake=pair<vll,vll>;

//(x,y)と(p,q)は隣接しているか?
bool is_adj(ll x,ll y,ll p,ll q){
    ll u=x-p;
    ll v=y-q;
    if(abs(u)+abs(v)==0)return 0;
    if(abs(u)+abs(v)==1)return 1;
    if(abs(u)+abs(v)==2&&u+v==0)return 1;
    return 0;
}



bool is_adj(snake &S1,snake &S2){
    return 0;
}

//(0,0)が頭の蛇がどう移動できるか? 長さ毎に管理
vector<map<snake,vector<snake>>> canmove(9);

//くねり方. 
//端:0,1,2 その他:0,1 
vector<vector<vector<ll>>> kuneri(9);


//蛇がvalidか?
bool is_valid(vll &X,vll &Y){
    ll N=X.size();
    set<pair<ll,ll>> S;
    rep(i,N){
        if(S.count({X[i],Y[i]}))return 0;
        S.insert({X[i],Y[i]});
    }
    rep(i,N-1){
        if(!is_adj(X[i],Y[i],X[i+1],Y[i+1]))return 0;
        if(i==N-2)return 1;
        if(is_adj(X[i],Y[i],X[i+2],Y[i+2]))return 0;
    }
    return 1;
}

//岩に載るか
bool over_rock(snake &S,set<pair<ll,ll>>&ROCK){
    ll N=S.first.size();
    rep(i,N)if(ROCK.count({S.first[i],S.second[i]}))return 1;
    return 0;
}

//頭が(0,0)なvalidな蛇全列挙
void making_snake(vll &X,vll &Y){
    if(X.size()>=2&&X.size()<=8){
        canmove[X.size()][snake({X,Y})]={};
    }
    if(X.size()==8)return;
    rep(d,6){
        X.push_back(X.back()+dx[d]);
        Y.push_back(Y.back()+dy[d]);
        if(is_valid(X,Y)){
            making_snake(X,Y);
        }
        X.pop_back();
        Y.pop_back();
    }
}

//くねり方全列挙
void making_kuneri(vll &K){
    if(K.size()==0){
        rep(i,3){
            K.push_back(i);
            making_kuneri(K);
            K.pop_back();
        }
    }
    else{
        rep(i,3){
            K.push_back(i);
            kuneri[K.size()].push_back(K);
            K.pop_back();
            if(K.back()!=0)break;
        }
        if(K.size()==7)return;
        rep(i,2){
            K.push_back(i);
            making_kuneri(K);
            K.pop_back();
            if(K.back()!=0)return;
        }
    }
}

//蛇Sのn節目をf移動.(f:1,2)
pair<ll,ll> trans(snake S,ll n,ll f){
    ll sz=S.first.size();
    if(n==0){
        if(f==1){
            ll x=S.first[0];
            ll y=S.second[0];
            rep(d,6){
                ll nx=x+dx[d];
                ll ny=y+dy[d];
                if(is_adj(nx,ny,S.first[1],S.second[1])){
                    return {nx,ny};
                }
            }
        }
        if(f==2){
            ll x=S.first[0];
            ll y=S.second[0];
            for(ll d=5;d>=0;d--){
                ll nx=x+dx[d];
                ll ny=y+dy[d];
                if(is_adj(nx,ny,S.first[1],S.second[1])){
                    return {nx,ny};
                }
            }
        }
    }
    else if(n+1==sz){
        if(f==1){
            ll x=S.first.back();
            ll y=S.second.back();
            rep(d,6){
                ll nx=x+dx[d];
                ll ny=y+dy[d];
                if(is_adj(nx,ny,S.first[sz-2],S.second[sz-2])){
                    return {nx,ny};
                }
            }
        }
        if(f==2){
            ll x=S.first[sz-1];
            ll y=S.second[sz-1];
            for(ll d=5;d>=0;d--){
                ll nx=x+dx[d];
                ll ny=y+dy[d];
                if(is_adj(nx,ny,S.first[sz-2],S.second[sz-2])){
                    return {nx,ny};
                }
            }
        }
    }
    else{
        ll x=S.first[n];
        ll y=S.second[n];
        rep(d,6){
            ll nx=x+dx[d];
            ll ny=y+dy[d];
            if(is_adj(nx,ny,S.first[n-1],S.second[n-1])&&is_adj(nx,ny,S.first[n+1],S.second[n+1])){
                return {nx,ny};
            }
        }
    }
    return {-1,-1};
}

ll ress=0;

//くねる.
void kuneru(){
    rep(sz,9){
        if(sz<2)continue;

        for(auto S:canmove[sz]){
            for(auto K:kuneri[sz]){
                vll NX(sz),NY(sz);
                rep(j,sz){
                    if(K[j]==0){
                        NX[j]=S.first.first[j];
                        NY[j]=S.first.second[j];
                    }
                    else{
                        auto XY=trans(S.first,j,K[j]);
                        NX[j]=XY.first;
                        NY[j]=XY.second;
                    }
                }
                snake NS={NX,NY};
                if(is_valid(NX,NY)){
                    canmove[sz][S.first].push_back(NS);
                }
            }
        }
    }
}

/*
前計算を行う
- (0,0)頭の蛇全列挙
- (0,0)頭の蛇の一手での移動先全列挙(124974ペアある. 長さを8に固定すれば91798通り. 1状態からの最大値は72通り)
*/
void init(){
    vll X={0},Y={0};
    vll K={};
    making_snake(X,Y);
    making_kuneri(K);
    kuneru();
}

void print(snake S){
    ll N=S.first.size();
    rep(i,N)cout<<"("<<S.first[i]<<","<<S.second[i]<<")";
    cout<<endl;
}

void solve(ll N) {
    vll X(N),Y(N);
    rep(i,N)cin>>X[i]>>Y[i];
    ll M;
    cin>>M;
    set<pair<ll,ll>> ROCK;
    rep(i,M){
        ll x,y;
        cin>>x>>y;
        ROCK.insert({x,y});
    }

    ll GX,GY;
    cin>>GX>>GY;
    map<snake,ll> dist;
    dist[{X,Y}]=0;
    queue<snake> Q;
    Q.push({X,Y});

    while(!Q.empty()){
        snake S=Q.front();
        Q.pop();
        snake MS=S;
        rep(i,N){
            MS.first[i]-=S.first[0];
            MS.second[i]-=S.second[0];
        }
        for(snake NS:canmove[N][MS]){
            rep(i,N){
                NS.first[i]+=S.first[0];
                NS.second[i]+=S.second[0];
            }
            if(abs(NS.second[0]-GY)>10||abs(NS.first[0]-GX)>20)continue;
            if(over_rock(NS,ROCK))continue;
            if(!dist.count(NS)){
                if(NS.first[0]==GX&&NS.second[0]==GY){
                    cout<<dist[S]+1<<endl;
                    return;
                }
                dist[NS]=dist[S]+1;
                Q.push(NS);
            }
        }
    }
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    init();

    
    ll N;
    while (cin >> N) {
        if (N == 0)return 0;
        solve(N);
    }

}
accuracy: 1
time_ms: 2970
memory_kb: 77472
final_rank: 16

code_snippet: #include <iostream>
#include <tuple>
#include <queue>
#include <vector>
using namespace std;

const int pows[8] = { 1, 6, 18, 54, 162, 486, 1458, 4374 };
const int dx[7] = { 0, -1, -1, 0, 1, 1, 0 };
const int dy[7] = { -1, 0, 1, 1, 0, -1, 0 };
int check_hairetsu[209][209];
vector<tuple<int, int, int>> tmp;

// ======================================================================================= Functions =======================================================================================
void Prepare() {
	for (int i = 0; i < 209; i++) {
		for (int j = 0; j < 209; j++) check_hairetsu[i][j] = -1;
	}
	for (int i = 0; i < 6; i++) check_hairetsu[100 + dx[i]][100 + dy[i]] = i;
}

int CheckOrientation(vector<pair<int, int>> vec) {
	// 条件を満たしているかチェック
	vector<int> Dir;
	for (int i = 0; i < (int)vec.size() - 1; i++) {
		int diff_x = 100 + vec[i + 1].first - vec[i].first;
		int diff_y = 100 + vec[i + 1].second - vec[i].second;
		if (check_hairetsu[diff_x][diff_y] == -1) return -1;
		Dir.push_back(check_hairetsu[diff_x][diff_y]);
	}

	// 癒着するかチェック
	for (int i = 0; i < (int)vec.size(); i++) {
		for (int j = i + 2; j < (int)vec.size(); j++) {
			int diff_x = 100 + vec[j].first - vec[i].first;
			int diff_y = 100 + vec[j].second - vec[i].second;
			if (diff_x == 100 && diff_y == 100) return -1;
			if (check_hairetsu[diff_x][diff_y] != -1) return -1;
		}
	}

	// 条件を満たしている場合
	int cur = Dir[0], mul = 6;
	for (int i = 1; i < (int)Dir.size(); i++) {
		int diff = (Dir[i] - Dir[i - 1] + 6) % 6;
		if (diff == -1) cur += 0 * mul;
		if (diff ==  0) cur += 1 * mul;
		if (diff == +1) cur += 2 * mul;
		mul *= 3;
	}
	return cur;
}

void DFSOrientation(vector<pair<int, int>> Fst, vector<pair<int, int>> Cur, bool Prev) {
	if (Fst.size() == Cur.size()) {
		int ret = CheckOrientation(Cur);
		if (ret != -1) tmp.push_back(make_tuple(Cur[0].first, Cur[0].second, ret));
		return;
	}

	// 全探索
	for (int i = 0; i < 7; i++) {
		if (Prev == true && i < 6) continue;
		int sx = Fst[Cur.size()].first + dx[i];
		int sy = Fst[Cur.size()].second + dy[i];
		bool flag = false;
		for (int j = 0; j < Cur.size(); j++) {
			if (Cur[j].first == sx && Cur[j].second == sy) flag = true;
		}
		if (flag == true) continue;

		// 再帰呼び出し
		vector<pair<int, int>> Nex = Cur;
		bool NexPrev = false; if (i < 6) NexPrev = true;
		Nex.push_back(make_pair(sx, sy));
		DFSOrientation(Fst, Nex, NexPrev);
	}
}

// ======================================================================================= Main Function =======================================================================================
int N, X[19], Y[19];
int K, U[19], V[19];
int SX, SY;
int Dist[29][29][4374];
bool Stone[29][29];
bool Variable[29][29][4374];
queue<tuple<int, int, int>> Q;
vector<tuple<int, int, int>> G[4374];
vector<tuple<int, int, int>> InitG[9][4374];

vector<pair<int, int>> GetOrientation(int n, int rx, int ry, int mask) {
	vector<pair<int, int>> Return;
	int sx = rx, sy = ry, dir = (mask % 6);
	Return.push_back(make_pair(sx, sy)); sx += dx[dir]; sy += dy[dir];
	Return.push_back(make_pair(sx, sy));
	for (int j = 2; j < n; j++) {
		int nex = (mask / pows[j - 1]) % 3;
		dir = (dir + nex + 5) % 6;
		sx += dx[dir];
		sy += dy[dir];
		Return.push_back(make_pair(sx, sy));
	}
	return Return;
}

void Initialize() {
	for (int i = 0; i < 4374; i++) G[i].clear();
	for (int i = 0; i < 29; i++) {
		for (int j = 0; j < 29; j++) Stone[i][j] = false;
	}
}

void Init_Enumerate() {
	for (int n = 2; n <= 8; n++) {
		for (int i = 0; i < pows[n - 1]; i++) {
			vector<pair<int, int>> vec = GetOrientation(n, 0, 0, i);
			int ret = CheckOrientation(vec);
			if (ret == -1) continue;
			tmp.clear();
			DFSOrientation(vec, vector<pair<int, int>>{}, false);
			for (tuple<int, int, int> j : tmp) InitG[n][i].push_back(j);
		}
	}
}

int main() {
	Prepare();
	Init_Enumerate();

	while (true) {
		// Step 1. Input
		Initialize();
		cin >> N; if (N == 0) break;
		for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];
		cin >> K;
		for (int i = 0; i < K; i++) cin >> U[i] >> V[i];
		cin >> SX >> SY;

		// Step 2. Adjust
		for (int i = 1; i < N; i++) X[i] = (X[i] - X[0] + 12);
		for (int i = 1; i < N; i++) Y[i] = (Y[i] - Y[0] + 12);
		for (int i = 0; i < K; i++) U[i] = (U[i] - X[0] + 12);
		for (int i = 0; i < K; i++) V[i] = (V[i] - Y[0] + 12);
		SX = (SX - X[0] + 12);
		SY = (SY - Y[0] + 12);
		X[0] = 12;
		Y[0] = 12;
		for (int i = 0; i < K; i++) {
			if (U[i] < 0 || U[i] > 24) continue;
			if (V[i] < 0 || V[i] > 24) continue;
			Stone[U[i]][V[i]] = true;
		}
		vector<pair<int, int>> InitState;
		for (int i = 0; i < N; i++) InitState.push_back(make_pair(X[i], Y[i]));
		int InitID = CheckOrientation(InitState);

		// Step 3. BFS Init
		for (int i = 0; i < pows[N - 1]; i++) G[i] = InitG[N][i];
		for (int i = 0; i <= 24; i++) {
			for (int j = 0; j <= 24; j++) {
				for (int k = 0; k < pows[N - 1]; k++) Dist[i][j][k] = 10000;
			}
		}
		Dist[12][12][InitID] = 0;
		Q.push(make_tuple(12, 12, InitID));

		// Step 4. BFS Init 2
		for (int i = 0; i <= 24; i++) {
			for (int j = 0; j <= 24; j++) {
				for (int k = 0; k < pows[N - 1]; k++) {
					vector<pair<int, int>> cur = GetOrientation(N, i, j, k);
					bool flag = false;
					for (pair<int, int> zahyou : cur) {
						if (zahyou.first < 0 || zahyou.first > 24 || zahyou.second < 0 || zahyou.second > 24) flag = true;
						else if (Stone[zahyou.first][zahyou.second] == true) flag = true;
					}
					if (flag == true) Variable[i][j][k] = false;
					else Variable[i][j][k] = true;
				}
			}
		}

		// Step 4. BFS
		while (!Q.empty()) {
			int pos1 = get<0>(Q.front());
			int pos2 = get<1>(Q.front());
			int pos3 = get<2>(Q.front()); Q.pop();
			for (tuple<int, int, int> to : G[pos3]) {
				int nex1 = pos1 + get<0>(to);
				int nex2 = pos2 + get<1>(to);
				int nex3 = get<2>(to);
				if (Variable[nex1][nex2][nex3] == false) continue;
				if (Dist[nex1][nex2][nex3] > Dist[pos1][pos2][pos3] + 1) {
					Dist[nex1][nex2][nex3] = Dist[pos1][pos2][pos3] + 1;
					Q.push(make_tuple(nex1, nex2, nex3));
				}
			}
		}

		// Step 5. Output
		int Answer = 10000;
		for (int i = 0; i < pows[N - 1]; i++) Answer = min(Answer, Dist[SX][SY][i]);
		cout << Answer << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 6890
memory_kb: 25856
final_rank: 11

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

int dx[] = { 0, 1, 1, 0,-1,-1};
int dy[] = {-1,-1, 0, 1, 1, 0};

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n;
    while (cin >> n, n) {
        vector<pair<int,int>> v(n);
        for (int i = 0; i < n; ++i) {
            cin >> v[i].first >> v[i].second;
        }
        int m; cin >> m;
        set<pair<int,int>> blc;
        for (int i = 0; i < m; ++i) {
            int x,y; cin >> x >> y;
            blc.insert({x, y});
        }
        int gx, gy; cin >> gx >> gy;
        using V = vector<pair<int,int>>;
        map<V, int> bfs;
        bfs[v] = 0;
        queue<V> q; q.push(v);
        while (q.size()) {
            auto p = q.front(); q.pop();
            int cost = bfs[p];
            
            vector<pair<int,int>> u;
            auto adj = [](pair<int,int> &p, pair<int,int> &q) -> bool {
                if (p == q) return true;
                if (abs(p.first-q.first) > 1 or abs(p.second-q.second) > 1) return false;
                if (p.first-q.first == p.second-q.second) return false;
                return true;
            };
            auto dfs = [&](auto dfs, int i) -> bool {
                if (i == n) {
                    // チェック
                    bool ok = true;
                    {
                        for (int j = 0; j < n; ++j) {
                            for (int k = j+2; k < n; ++k) {
                                if (adj(u[j], u[k])) {
                                    ok = false;
                                }
                            }
                        }
                    }
                    if (!ok) return false;
                    if (u[0].first == gx and u[0].second == gy) {
                        return true;
                    }
                    if (bfs.find(u) == bfs.end()) {
                        bfs[u] = cost + 1;
                        q.push(u);
                    }
                    return false;
                }
                for (int j = 0; j < 6; ++j) {
                    int nx = p[i].first + dx[j];
                    int ny = p[i].second + dy[j];
                    pair<int,int> nxt = {nx, ny};
                    if (blc.find({nx,ny}) != blc.end()) continue;
                    if (i and p[i-1] == nxt) continue;
                    if (i and !adj(p[i-1], nxt)) continue;
                    if (i+1 < p.size() and p[i+1] == nxt) continue;
                    if (i+1 < p.size() and !adj(nxt, p[i+1])) continue;
                    {
                        u.push_back({nx, ny});
                        int id = i+1;
                        if (id < p.size()) {
                            u.push_back(p[id]);
                            id += 1;
                        }
                        if (dfs(dfs, id)) return true;
                        if (id != i+1) u.pop_back();
                        u.pop_back();
                    }
                }
                // そのまま
                {
                    u.push_back(p[i]);
                    if (dfs(dfs, i+1)) return true;
                    u.pop_back();
                }
                return false;
            };
            if (dfs(dfs, 0)) {
                cout << cost + 1 << endl;
                break;
            }
        }
    }
}
accuracy: 1
time_ms: 3390
memory_kb: 32376
final_rank: 9

code_snippet: #include<bits/stdc++.h>
#define rep(i,a,...) for(int i = (a)*(strlen(#__VA_ARGS__)!=0);i<(int)(strlen(#__VA_ARGS__)?__VA_ARGS__:(a));++i)
#define per(i,a,...) for(int i = (strlen(#__VA_ARGS__)?__VA_ARGS__:(a))-1;i>=(int)(strlen(#__VA_ARGS__)?(a):0);--i)
#define foreach(i, n) for(auto &i:(n))
#define all(x) (x).begin(), (x).end()
#define bit(x) (1ll << (x))
#define lambda(RES_TYPE, ...) (function<RES_TYPE(__VA_ARGS__)>)[&](__VA_ARGS__) -> RES_TYPE
#define method(FUNC_NAME, RES_TYPE, ...) function<RES_TYPE(__VA_ARGS__)> FUNC_NAME = lambda(RES_TYPE, __VA_ARGS__)
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
//const ll MOD = (ll)1e9+7;
const ll MOD = 998244353;
const int INF = (ll)1e9+7;
const ll INFLL = (ll)1e18;
template<class t>
using vvector = vector<vector<t>>;
template<class t>
using vvvector = vector<vector<vector<t>>>;
template<class t>
using priority_queuer = priority_queue<t, vector<t>, greater<t>>;
template<class t, class u> bool chmax(t &a, u b){if(a<b){a=b;return true;}return false;}
template<class t, class u> bool chmin(t &a, u b){if(a>b){a=b;return true;}return false;}
#ifdef DEBUG
#define debug(x) cout<<"LINE "<<__LINE__<<": "<<#x<<" = "<<x<<endl;
#else
#define debug(x) (void)0
#endif

namespace templates{
    ll modpow(ll x, ll b,ll mod=MOD){
        ll res = 1;
        while(b){
            if(b&1)res = res * x % mod;
            x = x * x % mod;
            b>>=1;
        }
        return res;
    }

    ll modinv(ll x){
        return modpow(x, MOD-2);
    }

    bool was_output = false;

    void print();
    template <class t> void print(const vector<t> &);
    template <class t, class u> void print(const pair<t, u> &);
    template <class t> void print(const t&);
    template <class Head, class... Tail> void print(const Head&, const Tail&...);

    template <class t> void println(const vector<vector<t>>&);
    template <class t> void println(const vector<t>&);
    template <class t> void println(const t&);
    template <class Head, class... Tail> void println(const Head&, const Tail&...);
    void println();
    void newline();

    void print(){
        return;
    }

    template <class t>
    void print(const vector<t>&x){
        for(const t&i:x)print(i);
    }
    template <class t, class u>
    void print(const pair<t,u>&p){
        print(p.first);
        print(p.second);
    }
    template <class t>
    void print(const t&x){
        if(was_output)cout<<" ";
        cout<<x;
        was_output = true;
    }
    template <class Head, class... Tail>
    void print(const Head&head,const Tail&...tail){
        print(head);
        print(tail...);
    }

    template<class t>
    void println(const vector<vector<t>>&x){
        for(vector<t> i:x)println(i);
    }
    template<class t>
    void println(const vector<t>&x){
        for(const t&i:x)print(i);
        println();
    }
    template <class t>
    void println(const t&x){
        print(x);
        println();
    }
    void println(){
        if(was_output){
            cout << endl;
            was_output = false;
        }
    }
    template <class Head, class... Tail>
    void println(const Head&head,const Tail&...tail){
        print(head);
        println(tail...);
    }

    void newline(){
        was_output = true;
        println();
    }

    template<class t>
    istream& operator>>(istream&is, vector<t>&x){
        for(auto &i:x)is >> i;
        return is;
    }

    template<class t, class u>
    istream& operator>>(istream&is, pair<t, u>&x){
        is >> x.first >> x.second;
        return is;
    }

    template<class t>
    ostream& operator<<(ostream&os, vector<t> &v){
        os << "{";
        for(t &i:v){
            os << i << ", ";
        }
        os << "}";
        return os;
    }

    template<class t = long long>
    t in(){
        t res; cin >> res; return res;
    }

    template<class t>
    vector<t> sorted(vector<t> line,function<bool(t,t)> comp=[](t a,t b){return a<b;}){
        sort(line.begin(),line.end(),comp);
        return line;
    }

    template<class t>
    vector<t> reversed(vector<t> line){
        reverse(line.begin(),line.end());
        return line;
    }
    string reversed(string str){
        reverse(str.begin(),str.end());
        return str;
    }

    long long gcd(long long a,long long b){
        while(b){
            a %= b;
            swap(a,b);
        }
        return a;
    }

    long long lcm(long long a,long long b){
        return a / gcd(a,b) * b;
    }

    class output_initializer{
    public:
        output_initializer(){
            ios::sync_with_stdio(false);
            cin.tie(nullptr);
            cout << setprecision(20);
        }
    };output_initializer OUTPUT_INITIALIZER_INSTANCE = output_initializer();
}

using namespace templates;

using P = pii;

P operator+(P a,P b){
    return P(a.first+b.first,a.second+b.second);
}

array<P,6> nexts(P pos){
    array<P,6> res;
    res[0] = pos+P(0,1);
    res[1] = pos+P(-1,1);
    res[2] = pos+P(1,0);
    res[3] = pos+P(0,-1);
    res[4] = pos+P(1,-1);
    res[5] = pos+P(-1,0);
    return res;
}

bool connected(P a,P b){
    int dx = a.first - b.first;
    int dy = a.second - b.second;
    return dx * dy < 1 and abs(dx) <= 1 and abs(dy) <= 1;
}

vvector<P> nexts(vector<P> snake){
    vvector<P> res;
    vector<P> current;
    set<P> has;
    method(rec,void,int p,bool last){
        if(p == snake.size()){
            res.emplace_back(current);
            return;
        }
        if(not last){
            foreach(next,nexts(snake[p])){
                if(has.count(next))continue;
                int cnt= 0;
                foreach(side,nexts(next)){
                    if(has.count(side))++cnt;
                }
                if(cnt>1)continue;
                if(current.size() and not connected(current.back(),next))continue;
                current.emplace_back(next);
                has.emplace(next);
                rec(p+1,true);
                current.pop_back();
                has.erase(next);
            }
        }
        {
            P next = snake[p];
            do{
                if(has.count(next))break;
                int cnt= 0;
                foreach(side,nexts(next)){
                    if(has.count(side))++cnt;
                }
                if(cnt>1)break;
                if(current.size() and not connected(current.back(),next))break;
                current.emplace_back(next);
                has.emplace(next);
                rec(p+1,false);
                current.pop_back();
                has.erase(next);
            }while(false);
        }
    };
    rec(0,false);
    return res;
}

class state{
public:
    int cost;
    vector<P> snake;
    P goal;
    int dist(){
        return abs(snake[0].first-goal.first) + abs(snake[0].second-goal.second);
    }
    state(int cost,vector<P> snake,P goal):cost(cost),snake(snake),goal(goal){}
};

bool operator<(state a,state b){
    return a.dist()+a.cost < b.dist()+b.cost;
}
bool operator>(state a,state b){
    return a.dist()+a.cost > b.dist()+b.cost;
}

int func(int n){
    vector<P> snake;
    rep(_,n){
        int x = in();
        int y = in();
        snake.emplace_back(x,y);
    }
    set<P> stones;
    int q = in();
    rep(_,q){
        int x = in();
        int y = in();
        stones.emplace(x,y);
    }
    P goal;
    goal.first = in();
    goal.second = in();
    map<vector<P>,int> m;
    priority_queuer<state> pq;
    map<P,int> heads;
    method(add,void,state p){
        if(m.count(p.snake) and m[p.snake] <= p.cost+p.dist())return;
        m[p.snake] = p.cost+p.dist();
        heads[p.snake[0]] = p.cost+p.dist();
        pq.emplace(p);
    };
    method(rock,bool,vector<P> p){
        foreach(i,p){
            if(stones.count(i))return true;
        }
        return false;
    };
    add(state(0,snake,goal));
    while(not heads.count(goal)){
        auto p = pq.top();
        pq.pop();
        foreach(next,nexts(p.snake)){
            if(not rock(next)){
                add(state(p.cost+1,next,goal));
            }
        }
    }
    return heads[goal];
}

int main(){
    while(true){
        int n = in();
        if(n==0)break;
        println(func(n));
    }
    return 0;
}
accuracy: 1
time_ms: 2340
memory_kb: 8072
final_rank: 1

code_snippet: #line 1 "/Users/nok0/Documents/Programming/nok0/cftemp.hpp"
#include <bits/stdc++.h>
using namespace std;

#pragma region Macros
// rep macro
#define foa(v, a) for(auto &v : a)
#define REPname(a, b, c, d, e, ...) e
#define REP(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int i = 0; i < (x); ++i)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define REPSname(a, b, c, ...) c
#define REPS(...) REPSname(__VA_ARGS__, REPS1, REPS0)(__VA_ARGS__)
#define REPS0(x) for(int i = 1; i <= (x); ++i)
#define REPS1(i, x) for(int i = 1; i <= (x); ++i)
#define RREPname(a, b, c, d, e, ...) e
#define RREP(...) RREPname(__VA_ARGS__, RREP3, RREP2, RREP1, RREP0)(__VA_ARGS__)
#define RREP0(x) for(int i = (x)-1; i >= 0; --i)
#define RREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define RREP2(i, r, l) for(int i = (r)-1; i >= (l); --i)
#define RREP3(i, r, l, c) for(int i = (r)-1; i >= (l); i -= (c))
#define RREPSname(a, b, c, ...) c
#define RREPS(...) RREPSname(__VA_ARGS__, RREPS1, RREPS0)(__VA_ARGS__)
#define RREPS0(x) for(int i = (x); i >= 1; --i)
#define RREPS1(i, x) for(int i = (x); i >= 1; --i)

// name macro
#define pb push_back
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define popcnt(x) __builtin_popcountll(x)
template <class T = int>
using V = std::vector<T>;
template <class T = int>
using VV = std::vector<std::vector<T>>;
template <class T>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
using ll = long long;
using ld = long double;
using int128 = __int128_t;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;

// input macro
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
	is >> p.first >> p.second;
	return is;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
	for(T &i : v) is >> i;
	return is;
}
std::istream &operator>>(std::istream &is, __int128_t &a) {
	std::string s;
	is >> s;
	__int128_t ret = 0;
	for(int i = 0; i < s.length(); i++)
		if('0' <= s[i] and s[i] <= '9')
			ret = 10 * ret + s[i] - '0';
	a = ret * (s[0] == '-' ? -1 : 1);
	return is;
}
namespace scanner {
void scan(int &a) { std::cin >> a; }
void scan(long long &a) { std::cin >> a; }
void scan(std::string &a) { std::cin >> a; }
void scan(char &a) { std::cin >> a; }
void scan(char a[]) { std::scanf("%s", a); }
void scan(double &a) { std::cin >> a; }
void scan(long double &a) { std::cin >> a; }
template <class T, class U>
void scan(std::pair<T, U> &p) { std::cin >> p; }
template <class T>
void scan(std::vector<T> &a) { std::cin >> a; }
void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &...tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#define VEC(type, name, size)     \
	std::vector<type> name(size); \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                                    \
	std::vector<std::vector<type>> name(h, std::vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)             \
	std::string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHAR(...)     \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DOUBLE(...)     \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)

// output-macro
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &a) {
	for(int i = 0; i < int(a.size()); ++i) {
		if(i) os << " ";
		os << a[i];
	}
	return os;
}
std::ostream &operator<<(std::ostream &dest, __int128_t &value) {
	std::ostream::sentry s(dest);
	if(s) {
		__uint128_t tmp = value < 0 ? -value : value;
		char buffer[128];
		char *d = std::end(buffer);
		do {
			--d;
			*d = "0123456789"[tmp % 10];
			tmp /= 10;
		} while(tmp != 0);
		if(value < 0) {
			--d;
			*d = '-';
		}
		int len = std::end(buffer) - d;
		if(dest.rdbuf()->sputn(d, len) != len) {
			dest.setstate(std::ios_base::badbit);
		}
	}
	return dest;
}
template <class T>
void print(const T a) { std::cout << a << '\n'; }
template <class Head, class... Tail>
void print(Head H, Tail... T) {
	std::cout << H << ' ';
	print(T...);
}
template <class T>
void printel(const T a) { std::cout << a << '\n'; }
template <class T>
void printel(const std::vector<T> &a) {
	for(const auto &v : a)
		std::cout << v << '\n';
}
template <class Head, class... Tail>
void printel(Head H, Tail... T) {
	std::cout << H << '\n';
	printel(T...);
}
void Yes(const bool b = true) { std::cout << (b ? "Yes\n" : "No\n"); }
void No() { std::cout << "No\n"; }
void YES(const bool b = true) { std::cout << (b ? "YES\n" : "NO\n"); }
void NO() { std::cout << "NO\n"; }
void err(const bool b = true) {
	if(b) {
		std::cout << "-1\n", exit(0);
	}
}

//debug macro
namespace debugger {
template <class T>
void view(const std::vector<T> &a) {
	std::cerr << "{ ";
	for(const auto &v : a) {
		std::cerr << v << ", ";
	}
	std::cerr << "\b\b }";
}
template <class T>
void view(const std::vector<std::vector<T>> &a) {
	std::cerr << "{\n";
	for(const auto &v : a) {
		std::cerr << "\t";
		view(v);
		std::cerr << "\n";
	}
	std::cerr << "}";
}
template <class T, class U>
void view(const std::vector<std::pair<T, U>> &a) {
	std::cerr << "{\n";
	for(const auto &p : a) std::cerr << "\t(" << p.first << ", " << p.second << ")\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &p : m) std::cerr << "\t[" << p.first << "] : " << p.second << "\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::pair<T, U> &p) { std::cerr << "(" << p.first << ", " << p.second << ")"; }
template <class T>
void view(const std::set<T> &s) {
	std::cerr << "{ ";
	for(auto &v : s) {
		view(v);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <class T>
void view(const T &e) { std::cerr << e; }
}  // namespace debugger
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	debugger::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(false)
#else
#define debug(...) (void(0))
#endif

// vector macro
template <class T>
int lb(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::lower_bound((a).begin(), (a).end(), (x))); }
template <class T>
int ub(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::upper_bound((a).begin(), (a).end(), (x))); }
template <class T>
void UNIQUE(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<T> press(std::vector<T> &a) {
	auto res = a;
	UNIQUE(res);
	for(auto &v : a)
		v = lb(res, v);
	return res;
}
#define SORTname(a, b, c, ...) c
#define SORT(...) SORTname(__VA_ARGS__, SORT1, SORT0, ...)(__VA_ARGS__)
#define SORT0(a) std::sort((a).begin(), (a).end())
#define SORT1(a, c) std::sort((a).begin(), (a).end(), [](const auto x, const auto y) { return x c y; })
template <class T>
void ADD(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v += x;
}
template <class T>
void SUB(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v -= x;
}
std::vector<std::pair<char, int>> rle(const string &s) {
	int n = s.size();
	std::vector<std::pair<char, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and s[l] == s[r]; r++) {}
		ret.emplace_back(s[l], r - l);
		l = r;
	}
	return ret;
}
template <class T>
std::vector<std::pair<T, int>> rle(const std::vector<T> &v) {
	int n = v.size();
	std::vector<std::pair<T, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and v[l] == v[r]; r++) {}
		ret.emplace_back(v[l], r - l);
		l = r;
	}
	return ret;
}
std::vector<int> iota(int n) {
	std::vector<int> p(n);
	std::iota(p.begin(), p.end(), 0);
	return p;
}
template <class T>
struct cum_vector {
public:
	cum_vector() = default;
	template <class U>
	cum_vector(const std::vector<U> &vec) : cum((int)vec.size() + 1) {
		for(int i = 0; i < (int)vec.size(); i++)
			cum[i + 1] = cum[i] + vec[i];
	}
	T prod(int l, int r) {
		return cum[r] - cum[l];
	}

private:
	std::vector<T> cum;
};

// math macro
template <class T, class U>
inline bool chmin(T &a, const U &b) { return a > b ? a = b, true : false; }
template <class T, class U>
inline bool chmax(T &a, const U &b) { return a < b ? a = b, true : false; }
template <class T>
T divup(T x, T y) { return (x + y - 1) / y; }
template <class T>
T POW(T a, long long n) {
	T ret = 1;
	while(n) {
		if(n & 1) ret *= a;
		a *= a;
		n >>= 1;
	}
	return ret;
}
// modpow
long long POW(long long a, long long n, const int mod) {
	long long ret = 1;
	a = (a % mod + mod) % mod;
	while(n) {
		if(n & 1) (ret *= a) %= mod;
		(a *= a) %= mod;
		n >>= 1;
	}
	return ret;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f) {
	while(abs(ok - ng) > 1) {
		T mid = (ok + ng) >> 1;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f, int loop) {
	for(int i = 0; i < loop; i++) {
		T mid = (ok + ng) / 2;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}

// others
struct fast_io {
	fast_io() {
		ios::sync_with_stdio(false);
		cin.tie(nullptr);
		cout << fixed << setprecision(15);
	}
} fast_io_;
const int inf = 1e9;
const ll INF = 1e18;
#pragma endregion

void main_();

int main() {
	main_();
	return 0;
}
#line 2 "c.cpp"

int n, k;
int near_x[6] = {0, 1, 1, 0, -1, -1};
int near_y[6] = {1, 0, -1, -1, 0, 1};
void main_() {
	auto adj = [&](int ax, int ay, int bx, int by) {
		if(ax == bx and ay == by) return true;
		REP(j, 6) {
			if(near_x[j] == bx - ax and near_y[j] == by - ay) return true;
		}
		return false;
	};
	auto adj_pair = [&](pii a, pii b) -> bool {
		return adj(a.first, a.second, b.first, b.second);
	};

	while(cin >> n, n) {
		set<pii> st;
		set<V<pii>> snakes_set;
		V<pii> tmp = {pii(0, 0)};

		{
			auto valid_in = [&]() {
				//debug(tmp);
				bool ok = 1;

				REP(i, n) {
					REP(j, i + 1, n) {
						if(j - i == 1) {
							ok &= adj_pair(tmp[i], tmp[j]);
						} else
							ok &= !adj_pair(tmp[i], tmp[j]);
					}
				}
				if(ok) snakes_set.insert(tmp);
			};
			auto dfs = [&](auto dfs, int i) -> void {
				if(SZ(tmp) == n) {
					valid_in();
					return;
				}
				REP(j, 6) {
					auto [x, y] = tmp.back();
					tmp.pb({x + near_x[j], y + near_y[j]});
					dfs(dfs, i + 1);
					tmp.pop_back();
				}
			};
			dfs(dfs, 0);
		}

		V<V<pii>> snakes;
		foa(v, snakes_set) snakes.pb(v);

		int S = SZ(snakes);
		map<V<pii>, int> snake_id;
		REP(i, S) { snake_id[snakes[i]] = i; }

		//id,x,y
		using T = tuple<int, int, int>;

		vector<vector<T>> graph(S);

		REP(bit, 1 << n) {
			if(bit == 0) continue;
			bool ok = 1;
			V<> move_id;
			REP(i, n)
			if(bit >> i & 1) move_id.pb(i);
			REP(i, n - 1) {
				if(bit >> i & 1 and bit >> (i + 1) & 1) {
					ok = 0;
					break;
				}
			}
			if(!ok) continue;
			REP(k, S) {
				auto snake = snakes[k];

				int top_x = 0, top_y = 0;

				auto dfs = [&](auto dfs, int z) -> void {
					if(z == SZ(move_id)) {
						auto copy_snake = snake;
						auto [sub_x, sub_y] = snake[0];
						for(auto &p : copy_snake) {
							p.first -= sub_x;
							p.second -= sub_y;
						}
						if(snake_id.count(copy_snake)) {
							graph[k].emplace_back(T(snake_id[copy_snake], top_x, top_y));
						}
						return;
					}
					int id = move_id[z];
					auto [x, y] = snake[id];
					REP(j, 6) {
						int nx = x + near_x[j];
						int ny = y + near_y[j];
						bool ok = 1;
						if(id - 1 >= 0) {
							ok &= adj_pair(snake[id - 1], pair{nx, ny});
						}
						if(id + 1 < n) {
							ok &= adj_pair(snake[id + 1], pair{nx, ny});
						}
						if(ok) {
							if(id == 0) {
								top_x = near_x[j];
								top_y = near_y[j];
							}
							snake[id] = {nx, ny};
							dfs(dfs, z + 1);
							snake[id] = {x, y};
							if(id == 0) {
								top_x = 0;
								top_y = 0;
							}
						}
					}
				};

				dfs(dfs, 0);
			}
		}

		VEC(pii, xy, n);
		INT(k);

		auto [sx, sy] = xy[0];
		for(auto &[x, y] : xy) x -= sx, y -= sy;

		set<pii> out;
		REP(i, k) {
			INT(x, y);
			out.insert({x - sx, y - sy});
		}

		INT(gx, gy);
		gx -= sx, gy -= sy;

		T s = T(snake_id[xy], 0, 0);
		map<T, int> dist;
		dist[s] = 0;
		queue<T> que;
		que.push(s);

		while(que.size()) {
			auto v = que.front();
			que.pop();
			if(dist[v] > 20) break;
			auto [id, x, y] = v;
			for(auto nxt_t : graph[id]) {
				auto [nid, dx, dy] = nxt_t;
				int nx = x + dx, ny = y + dy;
				if(dist.count(T(nid, nx, ny))) continue;
				bool ok = 1;
				REP(i, n) {
					if(out.count({nx + snakes[nid][i].first, ny + snakes[nid][i].second})) {
						ok = 0;
						break;
					}
				}
				const auto next_t = T(nid, nx, ny);
				if(ok) {
					dist[next_t] = dist[v] + 1;
					if(nx == gx and ny == gy) {
						print(dist[next_t]);
						goto fin;
					}
					que.push(T(nid, nx, ny));
				}
			}
		}
	fin:;
	}
}
accuracy: 1
time_ms: 2240
memory_kb: 17848
final_rank: 4

code_snippet: #line 1 "/Users/nok0/Documents/Programming/nok0/cftemp.hpp"
#include <bits/stdc++.h>
using namespace std;

#pragma region Macros
// rep macro
#define foa(v, a) for(auto &v : a)
#define REPname(a, b, c, d, e, ...) e
#define REP(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int i = 0; i < (x); ++i)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define REPSname(a, b, c, ...) c
#define REPS(...) REPSname(__VA_ARGS__, REPS1, REPS0)(__VA_ARGS__)
#define REPS0(x) for(int i = 1; i <= (x); ++i)
#define REPS1(i, x) for(int i = 1; i <= (x); ++i)
#define RREPname(a, b, c, d, e, ...) e
#define RREP(...) RREPname(__VA_ARGS__, RREP3, RREP2, RREP1, RREP0)(__VA_ARGS__)
#define RREP0(x) for(int i = (x)-1; i >= 0; --i)
#define RREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define RREP2(i, r, l) for(int i = (r)-1; i >= (l); --i)
#define RREP3(i, r, l, c) for(int i = (r)-1; i >= (l); i -= (c))
#define RREPSname(a, b, c, ...) c
#define RREPS(...) RREPSname(__VA_ARGS__, RREPS1, RREPS0)(__VA_ARGS__)
#define RREPS0(x) for(int i = (x); i >= 1; --i)
#define RREPS1(i, x) for(int i = (x); i >= 1; --i)

// name macro
#define pb push_back
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define popcnt(x) __builtin_popcountll(x)
template <class T = int>
using V = std::vector<T>;
template <class T = int>
using VV = std::vector<std::vector<T>>;
template <class T>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
using ll = long long;
using ld = long double;
using int128 = __int128_t;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;

// input macro
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
	is >> p.first >> p.second;
	return is;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
	for(T &i : v) is >> i;
	return is;
}
std::istream &operator>>(std::istream &is, __int128_t &a) {
	std::string s;
	is >> s;
	__int128_t ret = 0;
	for(int i = 0; i < s.length(); i++)
		if('0' <= s[i] and s[i] <= '9')
			ret = 10 * ret + s[i] - '0';
	a = ret * (s[0] == '-' ? -1 : 1);
	return is;
}
namespace scanner {
void scan(int &a) { std::cin >> a; }
void scan(long long &a) { std::cin >> a; }
void scan(std::string &a) { std::cin >> a; }
void scan(char &a) { std::cin >> a; }
void scan(char a[]) { std::scanf("%s", a); }
void scan(double &a) { std::cin >> a; }
void scan(long double &a) { std::cin >> a; }
template <class T, class U>
void scan(std::pair<T, U> &p) { std::cin >> p; }
template <class T>
void scan(std::vector<T> &a) { std::cin >> a; }
void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &...tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#define VEC(type, name, size)     \
	std::vector<type> name(size); \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                                    \
	std::vector<std::vector<type>> name(h, std::vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)             \
	std::string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHAR(...)     \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DOUBLE(...)     \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)

// output-macro
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &a) {
	for(int i = 0; i < int(a.size()); ++i) {
		if(i) os << " ";
		os << a[i];
	}
	return os;
}
std::ostream &operator<<(std::ostream &dest, __int128_t &value) {
	std::ostream::sentry s(dest);
	if(s) {
		__uint128_t tmp = value < 0 ? -value : value;
		char buffer[128];
		char *d = std::end(buffer);
		do {
			--d;
			*d = "0123456789"[tmp % 10];
			tmp /= 10;
		} while(tmp != 0);
		if(value < 0) {
			--d;
			*d = '-';
		}
		int len = std::end(buffer) - d;
		if(dest.rdbuf()->sputn(d, len) != len) {
			dest.setstate(std::ios_base::badbit);
		}
	}
	return dest;
}
template <class T>
void print(const T a) { std::cout << a << '\n'; }
template <class Head, class... Tail>
void print(Head H, Tail... T) {
	std::cout << H << ' ';
	print(T...);
}
template <class T>
void printel(const T a) { std::cout << a << '\n'; }
template <class T>
void printel(const std::vector<T> &a) {
	for(const auto &v : a)
		std::cout << v << '\n';
}
template <class Head, class... Tail>
void printel(Head H, Tail... T) {
	std::cout << H << '\n';
	printel(T...);
}
void Yes(const bool b = true) { std::cout << (b ? "Yes\n" : "No\n"); }
void No() { std::cout << "No\n"; }
void YES(const bool b = true) { std::cout << (b ? "YES\n" : "NO\n"); }
void NO() { std::cout << "NO\n"; }
void err(const bool b = true) {
	if(b) {
		std::cout << "-1\n", exit(0);
	}
}

//debug macro
namespace debugger {
template <class T>
void view(const std::vector<T> &a) {
	std::cerr << "{ ";
	for(const auto &v : a) {
		std::cerr << v << ", ";
	}
	std::cerr << "\b\b }";
}
template <class T>
void view(const std::vector<std::vector<T>> &a) {
	std::cerr << "{\n";
	for(const auto &v : a) {
		std::cerr << "\t";
		view(v);
		std::cerr << "\n";
	}
	std::cerr << "}";
}
template <class T, class U>
void view(const std::vector<std::pair<T, U>> &a) {
	std::cerr << "{\n";
	for(const auto &p : a) std::cerr << "\t(" << p.first << ", " << p.second << ")\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &p : m) std::cerr << "\t[" << p.first << "] : " << p.second << "\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::pair<T, U> &p) { std::cerr << "(" << p.first << ", " << p.second << ")"; }
template <class T>
void view(const std::set<T> &s) {
	std::cerr << "{ ";
	for(auto &v : s) {
		view(v);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <class T>
void view(const T &e) { std::cerr << e; }
}  // namespace debugger
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	debugger::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(false)
#else
#define debug(...) (void(0))
#endif

// vector macro
template <class T>
int lb(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::lower_bound((a).begin(), (a).end(), (x))); }
template <class T>
int ub(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::upper_bound((a).begin(), (a).end(), (x))); }
template <class T>
void UNIQUE(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<T> press(std::vector<T> &a) {
	auto res = a;
	UNIQUE(res);
	for(auto &v : a)
		v = lb(res, v);
	return res;
}
#define SORTname(a, b, c, ...) c
#define SORT(...) SORTname(__VA_ARGS__, SORT1, SORT0, ...)(__VA_ARGS__)
#define SORT0(a) std::sort((a).begin(), (a).end())
#define SORT1(a, c) std::sort((a).begin(), (a).end(), [](const auto x, const auto y) { return x c y; })
template <class T>
void ADD(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v += x;
}
template <class T>
void SUB(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v -= x;
}
std::vector<std::pair<char, int>> rle(const string &s) {
	int n = s.size();
	std::vector<std::pair<char, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and s[l] == s[r]; r++) {}
		ret.emplace_back(s[l], r - l);
		l = r;
	}
	return ret;
}
template <class T>
std::vector<std::pair<T, int>> rle(const std::vector<T> &v) {
	int n = v.size();
	std::vector<std::pair<T, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and v[l] == v[r]; r++) {}
		ret.emplace_back(v[l], r - l);
		l = r;
	}
	return ret;
}
std::vector<int> iota(int n) {
	std::vector<int> p(n);
	std::iota(p.begin(), p.end(), 0);
	return p;
}
template <class T>
struct cum_vector {
public:
	cum_vector() = default;
	template <class U>
	cum_vector(const std::vector<U> &vec) : cum((int)vec.size() + 1) {
		for(int i = 0; i < (int)vec.size(); i++)
			cum[i + 1] = cum[i] + vec[i];
	}
	T prod(int l, int r) {
		return cum[r] - cum[l];
	}

private:
	std::vector<T> cum;
};

// math macro
template <class T, class U>
inline bool chmin(T &a, const U &b) { return a > b ? a = b, true : false; }
template <class T, class U>
inline bool chmax(T &a, const U &b) { return a < b ? a = b, true : false; }
template <class T>
T divup(T x, T y) { return (x + y - 1) / y; }
template <class T>
T POW(T a, long long n) {
	T ret = 1;
	while(n) {
		if(n & 1) ret *= a;
		a *= a;
		n >>= 1;
	}
	return ret;
}
// modpow
long long POW(long long a, long long n, const int mod) {
	long long ret = 1;
	a = (a % mod + mod) % mod;
	while(n) {
		if(n & 1) (ret *= a) %= mod;
		(a *= a) %= mod;
		n >>= 1;
	}
	return ret;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f) {
	while(abs(ok - ng) > 1) {
		T mid = (ok + ng) >> 1;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f, int loop) {
	for(int i = 0; i < loop; i++) {
		T mid = (ok + ng) / 2;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}

// others
struct fast_io {
	fast_io() {
		ios::sync_with_stdio(false);
		cin.tie(nullptr);
		cout << fixed << setprecision(15);
	}
} fast_io_;
const int inf = 1e9;
const ll INF = 1e18;
#pragma endregion

void main_();

int main() {
	main_();
	return 0;
}
#line 2 "c.cpp"

int n, k;
int near_x[6] = {0, 1, 1, 0, -1, -1};
int near_y[6] = {1, 0, -1, -1, 0, 1};
void main_() {
	auto adj = [&](int ax, int ay, int bx, int by) {
		if(ax == bx and ay == by) return true;
		REP(j, 6) {
			if(near_x[j] == bx - ax and near_y[j] == by - ay) return true;
		}
		return false;
	};
	auto adj_pair = [&](pii a, pii b) -> bool {
		return adj(a.first, a.second, b.first, b.second);
	};

	while(cin >> n, n) {
		set<pii> st;
		set<V<pii>> snakes_set;
		V<pii> tmp = {pii(0, 0)};

		{
			auto valid_in = [&]() {
				//debug(tmp);
				bool ok = 1;

				REP(i, n) {
					REP(j, i + 1, n) {
						if(j - i == 1) {
							ok &= adj_pair(tmp[i], tmp[j]);
						} else
							ok &= !adj_pair(tmp[i], tmp[j]);
					}
				}
				if(ok) snakes_set.insert(tmp);
			};
			auto dfs = [&](auto dfs, int i) -> void {
				if(SZ(tmp) == n) {
					valid_in();
					return;
				}
				REP(j, 6) {
					auto [x, y] = tmp.back();
					tmp.pb({x + near_x[j], y + near_y[j]});
					dfs(dfs, i + 1);
					tmp.pop_back();
				}
			};
			dfs(dfs, 0);
		}

		V<V<pii>> snakes;
		foa(v, snakes_set) snakes.pb(v);

		int S = SZ(snakes);
		map<V<pii>, int> snake_id;
		REP(i, S) { snake_id[snakes[i]] = i; }

		//id,x,y
		using T = tuple<int, int, int>;

		vector<vector<T>> graph(S);

		REP(bit, 1 << n) {
			if(bit == 0) continue;
			bool ok = 1;
			V<> move_id;
			REP(i, n)
			if(bit >> i & 1) move_id.pb(i);
			REP(i, n - 1) {
				if(bit >> i & 1 and bit >> (i + 1) & 1) {
					ok = 0;
					break;
				}
			}
			if(!ok) continue;
			REP(k, S) {
				auto snake = snakes[k];

				int top_x = 0, top_y = 0;

				auto dfs = [&](auto dfs, int z) -> void {
					if(z == SZ(move_id)) {
						auto copy_snake = snake;
						auto [sub_x, sub_y] = snake[0];
						for(auto &p : copy_snake) {
							p.first -= sub_x;
							p.second -= sub_y;
						}
						if(snake_id.count(copy_snake)) {
							graph[k].emplace_back(T(snake_id[copy_snake], top_x, top_y));
						}
						return;
					}
					int id = move_id[z];
					auto [x, y] = snake[id];
					REP(j, 6) {
						int nx = x + near_x[j];
						int ny = y + near_y[j];
						bool ok = 1;
						if(id - 1 >= 0) {
							ok &= adj_pair(snake[id - 1], pair{nx, ny});
						}
						if(id + 1 < n) {
							ok &= adj_pair(snake[id + 1], pair{nx, ny});
						}
						if(ok) {
							if(id == 0) {
								top_x = near_x[j];
								top_y = near_y[j];
							}
							snake[id] = {nx, ny};
							dfs(dfs, z + 1);
							snake[id] = {x, y};
							if(id == 0) {
								top_x = 0;
								top_y = 0;
							}
						}
					}
				};

				dfs(dfs, 0);
			}
		}

		VEC(pii, xy, n);
		INT(k);

		auto [sx, sy] = xy[0];
		for(auto &[x, y] : xy) x -= sx, y -= sy;

		set<pii> out;
		REP(i, k) {
			INT(x, y);
			out.insert({x - sx, y - sy});
		}

		INT(gx, gy);
		gx -= sx, gy -= sy;

		T s = T(snake_id[xy], 0, 0);
		map<T, int> dist;
		dist[s] = 0;
		queue<T> que;
		que.push(s);

		while(que.size()) {
			auto v = que.front();
			que.pop();
			if(dist[v] > 20) break;
			auto [id, x, y] = v;
			for(auto nxt_t : graph[id]) {
				auto [nid, dx, dy] = nxt_t;
				int nx = x + dx, ny = y + dy;
				if(dist.count(T(nid, nx, ny))) continue;
				bool ok = 1;
				REP(i, n) {
					if(out.count({nx + snakes[nid][i].first, ny + snakes[nid][i].second})) {
						ok = 0;
						break;
					}
				}
				const auto next_t = T(nid, nx, ny);
				if(ok) {
					dist[next_t] = dist[v] + 1;
					if(nx == gx and ny == gy) {
						print(dist[next_t]);
						goto fin;
					}
					que.push(T(nid, nx, ny));
				}
			}
		}
	fin:;
	}
}
accuracy: 1
time_ms: 2220
memory_kb: 17888
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=15,INF=1<<30;

vector<int> dx={0,1,1,0,-1,-1},dy={-1,-1,0,1,1,0};

vector<int> use[10];

bool connect(pair<int,int> a,pair<int,int> b){
    if(a==b) return false;
    if(abs(a.fi-b.fi)>=2||abs(a.se-b.se)>=2) return false;
    for(int k=0;k<6;k++){
        if(a.fi+dx[k]==b.fi&&a.se+dy[k]==b.se) return true;
    }
    swap(a,b);
    for(int k=0;k<6;k++){
        if(a.fi+dx[k]==b.fi&&a.se+dy[k]==b.se) return true;
    }
    return false;
}

set<pair<int,int>> ng;

vector<vector<pair<int,int>>> kouho;

vector<pair<int,int>> state;
void DFS(int u,int dir){
    if(u==si(state)){
        kouho.push_back(state);
        return;
    }
    if(dir&(1<<u)){
        for(int k=0;k<6;k++){
            state[u].fi+=dx[k];
            state[u].se+=dy[k];
            bool f=true;
            if(u>=2&&connect(state[u-2],state[u])) f=false;
            if(u>=2&&state[u-2]==state[u]) f=false;
            if(u>=1&&state[u-1]==state[u]) f=false;
            if(u>=1&&!connect(state[u-1],state[u])) f=false;
            if(f){
                if(ng.count(state[u])) f=false;
            }
            
            if(f){
                DFS(u+1,dir);
            }
            
            state[u].fi-=dx[k];
            state[u].se-=dy[k];
        }
    }else{
        if(u>=2&&connect(state[u-2],state[u])) return;
        if(u>=2&&state[u-2]==state[u]) return;
        if(u>=1&&state[u-1]==state[u]) return;
        if(u>=1&&!connect(state[u-1],state[u])) return;
        DFS(u+1,dir);
    }
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    for(int n=2;n<=8;n++){
        for(int bit=1;bit<(1<<n);bit++){
            bool f=true;
            for(int i=0;i+1<n;i++){
                if((bit&(1<<i))&&(bit&(1<<(i+1)))) f=false;
            }
            if(f) use[n].push_back(bit);
        }
    }
    
    while(1){
        int N;cin>>N;
        if(N==0) break;
        ng.clear();
        vector<pair<int,int>> S(N);
        for(int i=0;i<N;i++){
            int a,b;cin>>a>>b;
            S[i]=mp(a,b);
        }
        int M;cin>>M;
        for(int i=0;i<M;i++){
            int a,b;cin>>a>>b;
            ng.insert(mp(a,b));
        }
        pair<int,int> g;cin>>g.fi>>g.se;
        
        set<vector<pair<int,int>>> now;
        now.insert(S);
        
        for(int q=0;q<=20;q++){
            bool done=false;
            for(auto a:now){
                if(a[0]==g){
                    cout<<q<<endl;
                    done=true;
                    break;
                }
            }
            if(done) break;
            
            set<vector<pair<int,int>>> nex;
            
            for(auto a:now){
                int d=max(abs(a[0].fi-g.fi),abs(a[0].se-g.se));
                if(d>20-q) continue;
                for(int dir:use[N]){
                    kouho.clear();
                    state=a;
                    DFS(0,dir);
                    for(auto b:kouho) nex.insert(b);
                }
            }
            
            now=nex;
        }
    }
}
accuracy: 1
time_ms: 12000
memory_kb: 17904
final_rank: 13

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 16;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

int dx[6] = { 1,1,0,-1,-1,0 };
int dy[6] = { -1,0,1,1,0,-1 };

bool isadj(P a, P b) {
	rep(d, 6) {
		int x = b.first + dx[d];
		int y = b.second + dy[d];
		if (a.first == x && a.second == y)return true;
	}
	return false;
}
map<P, bool> mp;
bool canadd(vector<P>& v, P a) {
	if (mp[a])return false;
	if (v.empty())return true;
	if (!isadj(v.back(), a))return false;
	rep(i, v.size() - 1) {
		if (isadj(v[i], a))return false;
		if (v[i] == a)return false;
	}
	return true;
}
vector<vector<P>> find_nexts(vector<P> v) {
	vector<vector<P>> res;
	int n = v.size();
	vector<P> cur;
	vector<bool> ch;
	function<void(int)> dfs = [&](int id) {
		if (id == n)res.push_back(cur);
		else {
			//not change
			if (canadd(cur, v[id])) {
				cur.push_back(v[id]);
				ch.push_back(0);
				dfs(id + 1);
				cur.pop_back();
				ch.pop_back();
			}
			//change
			if (ch.empty() || ch.back() == 0) {
				rep(d, 6) {
					P p = { v[id].first + dx[d],v[id].second + dy[d] };
					if (canadd(cur, p)) {
						cur.push_back(p);
						ch.push_back(1);
						dfs(id + 1);
						cur.pop_back();
						ch.pop_back();
					}
				}
			}
		}
	};
	dfs(0);
	/*for (int i = 1; i < (1 << n); i++) {
		vector<int> c;
		rep(j, n)if (i & (1 << j))c.push_back(j);
		bool valid = true;
		rep(j, c.size() - 1)if (c[j] + 1 == c[j + 1])valid = false;
		if (!valid)continue;
		vector<P> cur;
		function<void(int)> dfs = [&](int id) {
			if (id == n) {
				//cout << "hello\n";
				res.push_back(cur);
				//
				return;
			}
			if (i & (1 << id)) {
				rep(d, 6) {
					int x = v[id].first + dx[d];
					int y = v[id].second + dy[d];
					P p = { x,y };
					if (canadd(cur, p)) {
						cur.push_back(p);
						dfs(id + 1);
						cur.pop_back();
					}
				}
			}
			else {
				if (canadd(cur, v[id])) {
					cur.push_back(v[id]);
					dfs(id + 1);
					cur.pop_back();
				}
			}
		};
		dfs(0);
	}*/
	return res;
}

int n;
void solve() {
	mp.clear();
	vector<P> ori(n);
	rep(i, n) {
		int x, y; cin >> x >> y;
		ori[i] = { x,y };
	}
	int m; cin >> m;
	rep(i, m) {
		int x, y; cin >> x >> y;
		mp[{x, y}] = true;
	}
	int gx, gy; cin >> gx >> gy;
	queue<vector<P>>q;
	map<vector<P>, bool> used;
	used[ori] = true; q.push(ori);
	int tmp = 0;
	//cout << "ans is ";
	while (!q.empty()) {
		tmp++;
		int len = q.size();
		//cout << len << "\n";
		rep(aa, len) {
			vector<P> v = q.front(); q.pop();
			vector<vector<P>> nvs = find_nexts(v);
			for (auto nv : nvs) {
				if (used[nv])continue;
				int dx = abs(gx - nv[0].first);
				int dy = abs(gy - nv[0].second);
				if (min(dx, dy) > 20-tmp)continue;
				if (nv[0].first == gx && nv[0].second == gy) {
					cout << tmp << "\n"; return;
				}
				q.push(nv);
				used[nv] = true;
			}
		}
	}
	assert(false);
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//expr();
	//int t; cin >> t;rep(i,t)
	while(cin>>n,n)
	solve();
	return 0;
}
accuracy: 1
time_ms: 4500
memory_kb: 25388
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;

#define EPS (1e-7)
#define INF (1e9)
#define PI (acos(-1))
//const ll mod = 1000000007;
int N;
map<i_i, bool> mp;
set<i_i> exist;
vector<vector<i_i>> serpents[25];
int dx[6] = {0, 1, 1, 0, -1, -1};
int dy[6] = {-1, -1, 0, 1, 1, 0};
int X, Y;
set<vector<i_i>> used;

bool valid(vector<i_i> &now) {
    exist.clear();
    for(int i = 0; i < now.size(); i++) {
        if(mp[now[i]]) return false;
        if(exist.find(now[i]) != exist.end()) return false;
        exist.insert(now[i]);
    }
    for(int i = 2; i < now.size(); i++) {
        for(int j = 0; j < 6; j++) {
            if(now[i].first == now[i-2].first + dx[j] && now[i].second == now[i-2].second + dy[j]) return false;
        }
    }
    return true;
}

bool connected(vector<i_i> &now) {
    for(int i = 1; i < now.size(); i++) {
        bool nowok = false;
        for(int j = 0; j < 6; j++) {
            if(now[i].first == now[i-1].first + dx[j] && now[i].second == now[i-1].second + dy[j]) nowok = true;
        }
        if(!nowok) return false;
    }
    return true;
}

void add(int T, vector<i_i> &serpent, int index) {
    if(!connected(serpent)) return;
    if(index >= serpent.size()) {
        if(valid(serpent)) {
            if(used.find(serpent) == used.end()) {
                serpents[T].push_back(serpent);
                used.insert(serpent);
            }
        }
        return;
    }
    for(int i = 0; i < 6; i++) {
        serpent[index].first += dx[i];
        serpent[index].second += dy[i];
        add(T, serpent, index + 2);
        serpent[index].first -= dx[i];
        serpent[index].second -= dy[i];
    }
    add(T, serpent, index + 1);
}

int main() {
    //cout.precision(10);
    while(true) {
        used.clear();
        cin >> N;
        if(N == 0) break;
        mp.clear();
        vector<i_i> initial(N);
        for(int i = 0; i <= 20; i++) serpents[i].clear();
        for(int i = 0; i < N; i++) {
            cin >> initial[i].first >> initial[i].second;
        }
        serpents[0].push_back(initial);
        int k;
        cin >> k;
        while(k--) {
            int u, v;
            cin >> u >> v;
            mp[{u, v}] = true;
        }
        cin >> X >> Y;
        //cout << valid(initial) << endl;
        bool cleared = false;
        for(int T = 0; T <= 20; T++) {
            if(cleared) break;
            //cerr << "T: " << T << endl;
            for(int i = 0; i < serpents[T].size(); i++) {
                vector<i_i> serpent = serpents[T][i];
                if(abs(X - serpent[0].first) + abs(Y - serpent[0].second) > 2 * (20 - T)) continue;
                /*
                cerr << T << ": ";
                for(int j = 0; j < serpent.size(); j++) {
                    cerr << "{" << serpent[j].first << ", " << serpent[j].second << "}, ";
                }
                cerr << endl;
                */
                if(serpent[0].first == X && serpent[0].second == Y) {
                    cout << T << endl;
                    cleared = true;
                    break;
                }
                add(T + 1, serpent, 0);
            }
        }
    }
    return 0;
}
accuracy: 1
time_ms: 13630
memory_kb: 30532
final_rank: 19

code_snippet: // Hexerpents of Hexwamp
#include <iostream>
#include <vector>
#include <set>
#include <queue>
#include <unordered_set>

namespace
{
    // a little helper that should IMHO be standardized
    template<typename T>
    std::size_t make_hash(const T& v)
    {
        return std::hash<T>()(v);
    }

    // adapted from boost::hash_combine
    void hash_combine(std::size_t& h, const std::size_t& v)
    {
        h ^= v + 0x9e3779b9 + (h << 6) + (h >> 2);
    }

    // hash any container
    template<typename T>
    struct hash_container
    {
        size_t operator()(const T& v) const
        {
            size_t h=0;
            for( const auto& e : v ) {
                hash_combine(h, make_hash(e));
            }
            return h;
        }
    };
}

namespace std
{
    // support for pair<T,U> if T and U can be hashed
    template<typename T, typename U>
    struct hash<pair<T, U>>
    {
        size_t operator()(const pair<T,U>& v) const
        {
            size_t h=make_hash(v.first);
            hash_combine(h, make_hash(v.second));
            return h;
        }
    };

    // support for vector<T> if T is hashable
    // (the T... is a required trick if the vector has a non-standard allocator)
    template<typename... T>
    struct hash<vector<T...>> : hash_container<vector<T...>> {};
}

using namespace std;

using P = pair<int, int>;

vector<P> dir{P(0, -1), P(0, 1), P(-1, 0), P(-1, 1), P(1, -1), P(1, 0)};

int is_valid_state(int state){
  while(state){
    if((state & 1) && (state & (1<<1))) return 0;
    state = state >> 1;
  }
  return 1;
}

int dist(P a, P b){
  return max(abs(a.first - b.first), max(abs(a.second - b.second), abs((a.second - b.second) + (a.first - b.first))));
}

int is_dead_serpent(vector<P>& serpent, unordered_set<P>& rock){
  for(int i=0;i<serpent.size();i++){
    for(int j=i+1;j<serpent.size();j++){
      P a = serpent[i];
      P b = serpent[j];
      int d = dist(a, b);
      if(d == 0) return 1;
      if(j - i != 1){
	if(d == 1) return 1;
      }else{
	if(d > 1) return 1;
      }
    }
  }

  for(int i=0;i<serpent.size();i++){
    if(rock.find(serpent[i]) != rock.end()) return 1;
  }    
  
  return 0;
}

int main(){
  int N;
  int K;
  int X, Y;
  while(cin >> N, N){
    vector<P>serpent(N);
    for(auto &s: serpent){
      cin >> s.first >> s.second;
    }

    cin >> K;
    unordered_set<P>rock;
    for(int i=0;i<K;i++){
      int x, y;
      cin >> x >> y;
      rock.insert(P(x, y));
    }
    cin >> X >> Y;
    P goal = P(X, Y);
    queue<pair<vector<P>, pair<int, int> >>que;
    unordered_set<vector<P> > visited;
    que.push(make_pair(serpent, make_pair(0, 0)));
    int maxcost = 0;
    while(!que.empty()){
      vector<P> ser = que.front().first;
      int cost = que.front().second.first;
      int last_state = que.front().second.second;
      que.pop();
      //if(maxcost < cost){
      //cout << cost << " " << que.size() << " " << visited.size() << endl;
      //	maxcost = cost;
      //}
      
      if(ser[0] == goal){
	cout << cost << endl;
	break;
      }
      if(visited.find(ser) != visited.end()) continue;
      visited.insert(ser);
      if(20 - cost < dist(ser[0], goal)) continue;

      for(int state = 1;state < (1<<N);state++){
	if(last_state & state & ((1<<(N-1)) - 2)) continue;
	//if(!((last_state&1) | (state&1))) continue;
	if(!is_valid_state(state)) continue;
	int num_move_section = __builtin_popcount(state);

	vector<int> next[4];
	int j = 0;
	int flag = 0;
	for(int i=0;i<num_move_section;i++){
	  while(!(state & (1<<j))) j++;
	  if(j == 0){
	    for(int k=0;k<6;k++){
	      if(dist(make_pair(ser[j].first + dir[k].first, ser[j].second + dir[k].second), ser[j+1]) == 1) next[i].push_back(k);
	    }
	  }else if(j == N-1){
	    for(int k=0;k<6;k++){
	      if(dist(make_pair(ser[j].first + dir[k].first, ser[j].second + dir[k].second), ser[j-1]) == 1) next[i].push_back(k);
	    }
	  }else{
	    for(int k=0;k<6;k++){
	      if(dist(make_pair(ser[j].first + dir[k].first, ser[j].second + dir[k].second), ser[j-1]) == 1 && dist(make_pair(ser[j].first + dir[k].first, ser[j].second + dir[k].second), ser[j+1]) == 1) next[i].push_back(k);
	    }
	    if(next[i].size() == 0) flag = 1;
	  }
	  j++;
	}
	if(flag) continue;
	
	vector<vector<int> >products(4, vector<int>(num_move_section, 0));
	if(next[0].size() == 2 && next[num_move_section-1].size() == 2){
	  products.resize(4);
	  products[1][0] = products[2][num_move_section-1] = products[3][0] = products[3][num_move_section-1] = 1;
	}else if(next[0].size() == 2){
	  products.resize(2);
	  products[1][0] = 1;	  
	}else if(next[num_move_section-1].size() == 2){
	  products.resize(2);
	  products[1][num_move_section-1] = 1;
	}else{
	  products.resize(1);
	}

	for(auto&& idxs: products){
	  vector<P> next_ser(ser);	  
	  int j = 0;
	  //cout << endl;
	  for(int i=0;i<num_move_section;i++){
	    while(!(state & (1<<j))) j++;

	    //for(auto &&x: ser){
	    //  cout << "(" << x.first << ", " << x.second << ") ";
	    //}cout << endl;

	    //cout << state << " " << j << " " << next_ser[j].first << " " << next_ser[j].second << " to ";
	    next_ser[j].first += dir[next[i][idxs[i]]].first;
	    next_ser[j].second += dir[next[i][idxs[i]]].second;
	    //cout << next_ser[j].first << " " << next_ser[j].second << endl;
	    j++;
	  }
	  if(is_dead_serpent(next_ser, rock)) continue;
	  if(visited.find(next_ser) != visited.end()) continue;
	  que.push(make_pair(next_ser, make_pair(cost + 1, state)));
	}
      }
    }
    //cout << que.size() << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 3520
memory_kb: 20776
final_rank: 5

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


#define NUM 500000
#define DIST_MAX 1000
#define SIZE 61

enum Type{
	No_Move,
	Up,
	Right_Up,
	Right_Under,
	Under,
	Left_Under,
	Left_Up,
};

struct LOC{
	void set(int arg_x,int arg_y){
		x = arg_x;
		y = arg_y;
	}
	bool operator==(const struct LOC &arg){
		return x == arg.x && y == arg.y;
	}
	bool operator !=(const struct LOC &arg){
		return x != arg.x || y != arg.y;
	}
	int x,y;
};

struct State{
	int num_parts;
	Type type[8]; //2個目以降の節が、1つ前の節と相対的にどの位置にあるか
};

struct Snake{
	int num_move,index,move_array[4];
	bool is_move[8];
	LOC tmp_loc[8];
};

struct Data{
	Data(int arg_x,int arg_y,short arg_sum_dist){
		x = arg_x;
		y = arg_y;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct Data &arg) const{
		return sum_dist > arg.sum_dist;
	}
	int x,y;
	short sum_dist;
};

struct Info{
	Info(int arg_head_x,int arg_head_y,int arg_state_code,short arg_sum_dist,LOC arg_pre_loc[8]){
		head_x = arg_head_x;
		head_y = arg_head_y;
		state_code = arg_state_code;
		sum_dist = arg_sum_dist;
		for(int i = 0; i < 8; i++){
			pre_loc[i] = arg_pre_loc[i];
		}
	}
	bool operator<(const struct Info &arg) const{
		return sum_dist > arg.sum_dist;
	}
	int head_x,head_y,state_code;
	short sum_dist;
	LOC pre_loc[8];
};

int N;
int diff_x[6] = {0,1,1,0,-1,-1},diff_y[6] = {-1,-1,0,1,1,0};
short min_dist[SIZE][SIZE],final_min_dist[SIZE][SIZE][6187];
int state_index;
int num_stone;
int POW[9];
bool is_stone[SIZE][SIZE];
vector<int> ADJ[6187][7]; //vector<int> ADJ[節の状態][頭の移動方向] = 隣接状態リスト
vector<int> MOVE_GROUP[9];
map<int,int> MAP; //MAP[形体] = stateにおけるインデックス
LOC loc_table[8],stone[105],goal;
State state[NUM];
Type type_array[7] = {No_Move,Up,Right_Up,Right_Under,Under,Left_Under,Left_Up},type_table[8];

bool rangeCheck(int x,int y){

	if(x >= 0 && x <= SIZE-1 && y >= 0 && y <= SIZE-1){
		return true;
	}else{
		return false;
	}
}

bool adj_check(int num_parts,LOC tmp_loc[8]);

int calc_state(int num_parts,LOC tmp_loc[8]){

	int tmp_table[8];
	int tmp_x,tmp_y;

	bool FLG;

	for(int i = 0; i < num_parts-1; i++){

		FLG = false;
		for(int k = 0; k < 6; k++){
			tmp_x = tmp_loc[i].x+diff_x[k];
			tmp_y = tmp_loc[i].y+diff_y[k];

			if(tmp_x == tmp_loc[i+1].x && tmp_y == tmp_loc[i+1].y){
				FLG = true;
				tmp_table[i] = k+1; //★★注意★★
				break;
			}
		}
	}

	int ret = 0;

	for(int i = 0; i < num_parts-1; i++){
		ret = 10*ret+tmp_table[i];
	}

	return MAP[ret];
}

void func(){

	LOC first_loc[8];

	for(int i = 0; i < N; i++){
		scanf("%d %d",&first_loc[i].x,&first_loc[i].y);
	}

	scanf("%d",&num_stone);

	for(int i = 0; i < num_stone; i++){
		scanf("%d %d",&stone[i].x,&stone[i].y);
	}

	int tmp_x,tmp_y;

	scanf("%d %d",&tmp_x,&tmp_y);

	//簡単のため、ゴールを移動する
	int plus_x = goal.x-tmp_x;
	int plus_y = goal.y-tmp_y;

	//座標を修正する
	for(int i = 0; i < N; i++){
		first_loc[i].x += plus_x;
		first_loc[i].y += plus_y;
	}

	for(int x = 0; x < SIZE; x++){
		for(int y = 0; y < SIZE; y++){
			is_stone[x][y] = false;
		}
	}

	for(int i = 0; i < num_stone; i++){
		stone[i].x += plus_x;
		stone[i].y += plus_y;

		if(rangeCheck(stone[i].x,stone[i].y)){
			is_stone[stone[i].x][stone[i].y] = true;
		}
	}

	for(int i = 0; i < SIZE; i++){
		for(int k = 0; k <  SIZE; k++){
			for(int a = 0; a < state_index; a++){
				final_min_dist[i][k][a] = DIST_MAX;
			}
		}
	}

	int first_state = calc_state(N,first_loc);

	LOC debug_loc[8];
	for(int i = 0; i < N; i++){
		debug_loc[i].set(-1,-1);
	}

	priority_queue<Info> Q;
	final_min_dist[first_loc[0].x][first_loc[0].y][first_state] = 0;
	Q.push(Info(first_loc[0].x,first_loc[0].y,first_state,0,debug_loc));

	int next_code,next_cost;
	LOC work[8];
	bool FLG;

	while(!Q.empty()){

		if(Q.top().head_x == goal.x && Q.top().head_y == goal.y){

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

		}else if(Q.top().sum_dist > final_min_dist[Q.top().head_x][Q.top().head_y][Q.top().state_code]){

			Q.pop();

		}else{

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

				if(i == 0){

					work[0].x = Q.top().head_x;
					work[0].y = Q.top().head_y;

				}else{

					work[0].x = Q.top().head_x + diff_x[i-1];
					work[0].y = Q.top().head_y + diff_y[i-1];
				}

				if(rangeCheck(work[0].x,work[0].y) == false || min_dist[work[0].x][work[0].y]+Q.top().sum_dist > 20){ //枝刈り
					continue;
				}

				for(int k = 0; k < ADJ[Q.top().state_code][i].size(); k++){

					next_code = ADJ[Q.top().state_code][i][k];

					//座標に配置
					for(int a = 0; a < N-1; a++){
						switch(state[next_code].type[a]){
						case Up:
							tmp_x = work[a].x;
							tmp_y = work[a].y-1;
							break;
						case Right_Up:
							tmp_x = work[a].x+1;
							tmp_y = work[a].y-1;
							break;
						case Right_Under:
							tmp_x = work[a].x+1;
							tmp_y = work[a].y;
							break;
						case Under:
							tmp_x = work[a].x;
							tmp_y = work[a].y+1;
							break;
						case Left_Under:
							tmp_x = work[a].x-1;
							tmp_y = work[a].y+1;
							break;
						case Left_Up:
							tmp_x = work[a].x-1;
							tmp_y = work[a].y;
							break;
						}
						work[a+1].set(tmp_x,tmp_y);
					}

					//石に接触しないかチェック
					FLG = true;

					for(int a = 0; a < N; a++){
						if(rangeCheck(work[a].x,work[a].y)){
							if(is_stone[work[a].x][work[a].y]){
								FLG = false;
								break;
							}
						}
					}
					if(!FLG){
						continue;
					}

					if(final_min_dist[work[0].x][work[0].y][next_code] > Q.top().sum_dist+1){

						final_min_dist[work[0].x][work[0].y][next_code] = Q.top().sum_dist+1;
						Q.push(Info(work[0].x,work[0].y,next_code,Q.top().sum_dist+1,work));
					}
				}
			}
			Q.pop();
		}
	}
}

int makeCode(int num_parts){

	int ret = 0;

	for(int i = 0; i < num_parts-1; i++){
		for(int k = 1; k <= 6; k++){
			if(type_table[i] == type_array[k]){
				ret = 10*ret+k;
				break;
			}
		}
	}

	return ret;
}

void makeState(int num_parts,int index){

	if(index == num_parts){

		state[state_index].num_parts = num_parts;
		for(int i = 0; i < num_parts-1; i++){
			state[state_index].type[i] = type_table[i];
		}

		MAP[makeCode(num_parts)] = state_index;

		state_index++;
		return;
	}

	int count;

	int next_x,next_y,tmp_x,tmp_y;

	for(int i = 0; i < 6; i++){ //最後のマスから、6近傍を探索

		next_x = loc_table[index-1].x+diff_x[i];
		next_y = loc_table[index-1].y+diff_y[i];

		//既に使用している節があればSKIP
		count = 0;
		for(int k = 0; k <= index-2; k++){
			if(loc_table[k].x == next_x && loc_table[k].y == next_y){
				count = 1;
				break;
			}
		}
		if(count != 0)continue;

		//今回のマス(末尾)が、loc_table[index-1]以外のマスと接していたらSKIP
		count = 0;
		for(int k = 0; k <= index-2; k++){
			for(int a = 0; a < 6; a++){
				tmp_x = loc_table[k].x+diff_x[a];
				tmp_y = loc_table[k].y+diff_y[a];

				if(tmp_x == next_x && tmp_y == next_y){
					count = 1;
					break;
				}
			}
			if(count != 0)break;
		}
		if(count != 0)continue;

		loc_table[index].set(next_x,next_y);
		type_table[index-1] = type_array[i+1]; //★★★+1に注意★★★

		makeState(num_parts,index+1);
	}
}

void calcMoveGroup(int num_parts){

	bool check[9];
	bool FLG;

	for(int state = 1; state < POW[num_parts]; state++){
		for(int loop = 0; loop < num_parts; loop++){
			if(state & (1 << loop)){
				check[loop] = true;
			}else{
				check[loop] = false;
			}
		}
		FLG = true;
		for(int i = 1; i < num_parts; i++){
			if(check[i] == true && check[i-1] == true){ //隣接する2個は同時には動けない
				FLG = false;
				break;
			}
		}
		if(FLG){
			MOVE_GROUP[num_parts].push_back(state);
		}
	}
}

//前の状態から見た、次の状態の相対位置を取得する関数
Type getRelativePos(LOC next,LOC pre){

	Type ret = No_Move;

	int tmp_x,tmp_y;
	for(int i = 0; i < 6; i++){
		tmp_x = pre.x+diff_x[i];
		tmp_y = pre.y+diff_y[i];

		if(tmp_x == next.x && tmp_y == next.y){
			return type_array[i+1]; //★★
		}
	}

	return ret;
}



bool adj_check(int num_parts,LOC tmp_loc[8]){

	int adj_count;
	int adj_x,adj_y;

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

		adj_count = 0;
		for(int k = 0; k < 6; k++){
			adj_x = tmp_loc[i].x+diff_x[k]; //現在のマスの、隣接マスを求める
			adj_y = tmp_loc[i].y+diff_y[k];

			for(int a = 0; a < num_parts; a++){ //そのマスを使っている節があるか
				if(a == i)continue;
				if(tmp_loc[a].x == adj_x && tmp_loc[a].y == adj_y){
					adj_count++;
					break;
				}
			}
		}
		if(i == 0 && adj_count != 1){

			return false;

		}else if(i > 0 && i < num_parts-1 && adj_count != 2){

			return false;

		}else if(i == num_parts-1 && adj_count != 1){

			return false;
		}
	}

	return true;
}

bool is_same_pos(int num_parts,LOC tmp_loc[8]){

	for(int i = 0; i < num_parts-1; i++){
		for(int k = i+1; k < num_parts; k++){
			if(tmp_loc[i].x == tmp_loc[k].x && tmp_loc[i].y == tmp_loc[k].y){
				return false;
			}
		}
	}

	return true;
}

//ある状態から遷移できる別の状態を洗い出す
void calc_adj_state(int index){

	int num_parts = state[index].num_parts;
	bool FLG;

	loc_table[0].set(0,0);

	int tmp_x,tmp_y;
	for(int i = 0; i < num_parts-1; i++){

		switch(state[index].type[i]){
		case Up:
			tmp_x = loc_table[i].x;
			tmp_y = loc_table[i].y-1;
			break;
		case Right_Up:
			tmp_x = loc_table[i].x+1;
			tmp_y = loc_table[i].y-1;
			break;
		case Right_Under:
			tmp_x = loc_table[i].x+1;
			tmp_y = loc_table[i].y;
			break;
		case Under:
			tmp_x = loc_table[i].x;
			tmp_y = loc_table[i].y+1;
			break;
		case Left_Under:
			tmp_x = loc_table[i].x-1;
			tmp_y = loc_table[i].y+1;
			break;
		case Left_Up:
			tmp_x = loc_table[i].x-1;
			tmp_y = loc_table[i].y;
			break;
		}
		loc_table[i+1].set(tmp_x,tmp_y);
	}

	int num_move,tmp_state,tmp_pos;
	queue<Snake> Q;
	//同時に動かす場所を全探索
	for(int i = 0; i < MOVE_GROUP[num_parts].size(); i++){
		num_move = 0;
		Snake tmp_snake;
		for(int k = 0; k < num_parts; k++){
			tmp_snake.tmp_loc[k] = loc_table[k];
		}
		tmp_state = MOVE_GROUP[num_parts][i];
		for(int loop = 0; loop < num_parts; loop++){
			if(tmp_state & (1 << loop)){
				tmp_snake.move_array[num_move] = loop;
				tmp_snake.is_move[loop] = true;
				num_move++;
			}else{
				tmp_snake.is_move[loop] = false;
			}
		}
		tmp_snake.index = 0;
		tmp_snake.num_move = num_move;
		Q.push(tmp_snake);
	}

	while(!Q.empty()){

		Snake tmp_snake = Q.front();
		Q.pop();

		if(tmp_snake.index == tmp_snake.num_move){ //移動完了

			//★同じ場所に2つ以上の節があればSKIP★
			if(!is_same_pos(num_parts,tmp_snake.tmp_loc)){
				continue;
			}

			//★隣接関係が不適ならSKIP★
			if(!adj_check(num_parts,tmp_snake.tmp_loc))continue;

			tmp_state = calc_state(num_parts,tmp_snake.tmp_loc);

			//頭の移動方向別に、隣接状態を格納
			Type tmp_type = getRelativePos(tmp_snake.tmp_loc[0],loc_table[0]);

			ADJ[index][tmp_type].push_back(tmp_state);

			continue;
		}

		tmp_pos = tmp_snake.move_array[tmp_snake.index]; //今回動かす場所

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

			tmp_x = tmp_snake.tmp_loc[tmp_pos].x+diff_x[i];
			tmp_y = tmp_snake.tmp_loc[tmp_pos].y+diff_y[i];

			FLG = true;
			//同じ場所に、別の節があったら不可
			for(int k = 0; k < num_parts; k++){
				if(k > tmp_pos && tmp_snake.is_move[k] == true)continue; //これから動くものはSKIP
				if(tmp_snake.tmp_loc[k].x == tmp_x && tmp_snake.tmp_loc[k].y == tmp_y){
					FLG = false;
					break;
				}
			}
			if(!FLG)continue;

			//1つ前の節と隣接していなければSKIP
			if(tmp_pos > 0){

				FLG = false;
				for(int a = 0; a < 6; a++){
					if(tmp_x == tmp_snake.tmp_loc[tmp_pos-1].x+diff_x[a] && tmp_y == tmp_snake.tmp_loc[tmp_pos-1].y+diff_y[a]){
						FLG = true;
						break;
					}
				}
				if(!FLG)continue;
			}

			//1つ後の節と隣接していなければSKIP
			if(tmp_pos < tmp_snake.num_move-1){
				FLG = false;
				for(int a = 0; a < 6; a++){
					if(tmp_x == tmp_snake.tmp_loc[tmp_pos+1].x+diff_x[a] && tmp_y == tmp_snake.tmp_loc[tmp_pos+1].y+diff_y[a]){
						FLG = true;
						break;
					}
				}
				if(!FLG)continue;
			}

			Snake next_snake;
			for(int k = 0; k < num_parts; k++){
				//debug++;
				next_snake.tmp_loc[k] = tmp_snake.tmp_loc[k];
				next_snake.is_move[k] = tmp_snake.is_move[k];
			}
			next_snake.index = tmp_snake.index+1;
			next_snake.num_move = tmp_snake.num_move;
			for(int k = 0; k < tmp_snake.num_move; k++){
				next_snake.move_array[k] = tmp_snake.move_array[k];
			}
			next_snake.tmp_loc[tmp_pos].set(tmp_x,tmp_y);
			Q.push(next_snake);
		}
	}

	for(int i = 0; i < 7; i++){
		sort(ADJ[index][i].begin(),ADJ[index][i].end());
		ADJ[index][i].erase(unique(ADJ[index][i].begin(),ADJ[index][i].end()),ADJ[index][i].end());
	}
}

void calc_min_dist(){

	for(int x = 0; x < SIZE; x++){
		for(int y = 0; y < SIZE; y++){
			min_dist[x][y] = DIST_MAX;
		}
	}

	min_dist[goal.x][goal.y] = 0;
	priority_queue<Data> Q;
	Q.push(Data(goal.x,goal.y,0));

	int next_x,next_y;

	while(!Q.empty()){

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

			next_x = Q.top().x+diff_x[i];
			next_y = Q.top().y+diff_y[i];

			if(!rangeCheck(next_x,next_y))continue;

			if(min_dist[next_x][next_y] > Q.top().sum_dist+1){
				min_dist[next_x][next_y] = Q.top().sum_dist+1;
				Q.push(Data(next_x,next_y,min_dist[next_x][next_y]));
			}
		}
		Q.pop();
	}
}

int main(){

	state_index = 0;

	//蛇のありえる形態を洗い出す(6186)
	for(int num_parts = 2; num_parts <= 8; num_parts++){
		loc_table[0].set(0,0);
		makeState(num_parts,1);
	}

	//同時に動かし得る、節の集合を列挙する
	POW[0] = 1;
	for(int i = 1; i <= 8; i++){
		POW[i] = POW[i-1]*2;
	}
	for(int num_parts = 2; num_parts <= 8; num_parts++){
		calcMoveGroup(num_parts);
	}

	//状態間の隣接関係を計算する
	for(int i = 0; i < state_index; i++){
		calc_adj_state(i);
	}

	//ゴールを固定する
	goal.set(SIZE/2,SIZE/2);

	//ゴール地点からの最短距離を計算する
	calc_min_dist();

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 900
memory_kb: 52028
final_rank: 10

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

#define x first
#define y second
using Point = pair<int, int>;

using Direction = int;
using Body = vector<Direction>;

struct Snake {
  Point head;
  Body body;
  bool operator<(auto s) const {return head != s.head ? head < s.head : body < s.body;}
};

const int D = 7;
const Direction DX[D] = {0,  0,  1, 1, 0, -1, -1};
const Direction DY[D] = {0, -1, -1, 0, 1,  1,  0};

bool valid(const Body& body) {
  static map<Body, bool> memo;
  if(memo.count(body)) return memo[body];
  const int N = 10;
  auto x = N, y = N;
  vector<vector<int>> f(2*N, vector<int>(2*N));
  for(auto d = 0; d < D; ++d) ++f[x+DX[d]][y+DY[d]];
  for(auto b: body) {
    x += DX[b];
    y += DY[b];
    for(auto d = 0; d < D; ++d) ++f[x+DX[d]][y+DY[d]];
  }
  x = y = N;
  if(f[x][y] != 2) return memo[body] = false;
  for(auto i = 0; i < body.size(); ++i) {
    x += DX[body[i]];
    y += DY[body[i]];
    if(i == body.size() - 1) {
      if(f[x][y] != 2) return memo[body] = false;
    } else {
      if(f[x][y] != 3) return memo[body] = false;
    }
  }
  return memo[body] = true;
}

Direction direction(const Point& p) {
  static map<Point, Direction> memo;
  if(memo.count(p)) return memo[p];
  for(auto d = 1; d < D; ++d) if(p.x == DX[d] && p.y == DY[d]) return memo[p] = d;
  return -1;
}

void next(vector<Snake>& res, vector<Point>& point, int depth, bool moved) {
  if(depth == point.size()) {
    Snake snake;
    snake.head = point[0];
    for(auto i = 1; i < point.size(); ++i) snake.body.emplace_back(direction(Point(point[i].x - point[i-1].x, point[i].y - point[i-1].y)));
    if(valid(snake.body)) res.emplace_back(snake);
    return;
  }
  next(res, point, depth + 1, false);
  if(moved) return;
  for(auto d = 1; d < D; ++d) {
    point[depth].x += DX[d];
    point[depth].y += DY[d];
    if(depth == 0 || direction(Point(point[depth].x - point[depth-1].x, point[depth].y - point[depth-1].y)) != -1)
      next(res, point, depth + 1, true);
    point[depth].x -= DX[d];
    point[depth].y -= DY[d];
  }
}

vector<Snake> next(const Snake& snake) {
  static map<Body, vector<Snake>> memo;
  if(memo.count(snake.body)) return memo[snake.body];
  vector<Point> point;
  point.emplace_back(0, 0);
  for(auto i = 0; i < snake.body.size(); ++i) {
    auto b = snake.body[i];
    auto x = point.back().x + DX[b];
    auto y = point.back().y + DY[b];
    point.emplace_back(x, y);
  }
  next(memo[snake.body], point, 0, false);
  return memo[snake.body];
}

set<Point> terrain(auto k, const auto& u, const auto& v) {
  set<Point> res;
  for(auto i = 0; i < k; ++i) res.emplace(u[i], v[i]);
  return res;
}

int solve(const auto& snake, const auto& rock, auto X, auto Y) {
  set<Snake> visited;
  queue<pair<int, Snake>> q;
  q.emplace(0, snake);
  while(!q.empty()) {
    int step;
    Snake cur;
    tie(step, cur) = q.front();
    q.pop();
    if(cur.head.x == X && cur.head.y == Y) return step;
    if(20-step < abs(X-cur.head.x)) continue;
    if(20-step < abs(Y-cur.head.y)) continue;
    if(visited.count(cur)) continue;
    visited.emplace(cur);
    for(auto nex: next(cur)) {
      nex.head.x += cur.head.x;
      nex.head.y += cur.head.y;
      auto p = nex.head;
      bool stranding = rock.count(p);
      for(auto b: nex.body) {
        p.x += DX[b];
        p.y += DY[b];
        stranding |= rock.count(p);
      }
      if(stranding) continue;
      if(!visited.count(nex)) q.emplace(step + 1, nex);
    }
  }
  assert(false);
}

int main() {
  int n;
  while(cin >> n, n) {
    vector<int> x(n), y(n);
    for(auto i = 0; i < n; ++i) cin >> x[i] >> y[i];
    int k;
    cin >> k;
    vector<int> u(k), v(k);
    for(auto i = 0; i < k; ++i) cin >> u[i] >> v[i];
    int X, Y;
    cin >> X >> Y;

    for(auto p: {&x, &y, &u, &v}) for(auto& i: *p) i += 1e6;
    for(auto p: {&X, &Y}) *p += 1e6;

    Snake snake;
    snake.head = {x[0], y[0]};
    for(auto i = 1; i < n; ++i) snake.body.emplace_back(direction({x[i] - x[i-1], y[i] - y[i-1]}));

    cout << solve(snake, terrain(k, u, v), X, Y) << endl;
  }
}
accuracy: 1
time_ms: 7380
memory_kb: 51076
final_rank: 14

code_snippet: #include<bits/stdc++.h>
using namespace std;
int ax[]={1,1,0,-1,-1,0};
int ay[]={0,-1,-1,0,1,1};
typedef pair<int,int> P;
typedef vector<P> VP;
#define X first
#define Y second
bool adj(P a,P b){
  for(int i=0;i<6;i++){
    if(a.X+ax[i]==b.X&&a.Y+ay[i]==b.Y)
      return 1;
  }
  return 0;
}
int n,m;
VP p,r;
vector<VP> t;
P g;
void dfs(int v,int f){
  //cout<<v<<" "<<f<<endl;
  if(v==n){
    t.push_back(p);
    return;
  }
  {  
    bool flg=(v==0)||adj(p[v-1],p[v]);
    for(int j=0;j<v-1;j++) flg&=!adj(p[j],p[v]);
    for(int j=0;j<v;j++) flg&=(p[j]!=p[v]);
    for(int j=0;j<m;j++) flg&=(r[j]!=p[v]);
    if(flg) dfs(v+1,0);
  }
  if(!f){
    for(int i=0;i<6;i++){
      p[v].X+=ax[i];
      p[v].Y+=ay[i];
      bool flg=(v==0)||adj(p[v-1],p[v]);
      for(int j=0;j<v-1;j++) flg&=!adj(p[j],p[v]);
      for(int j=0;j<v;j++) flg&=(p[j]!=p[v]);
      for(int j=0;j<m;j++) flg&=(r[j]!=p[v]);
      if(flg) dfs(v+1,1);
      p[v].X-=ax[i];
      p[v].Y-=ay[i];
    }
  }
}
void dfs2(int v){
  if(v==n){
    t.push_back(p);
    return;
  }
  if(v==0){
    p[0]=g;
    dfs2(v+1);
    return;
  }
  for(int i=0;i<6;i++){
    p[v].X=p[v-1].X+ax[i];
    p[v].Y=p[v-1].Y+ay[i];
    bool flg=(v==0)||adj(p[v-1],p[v]);
    for(int j=0;j<v-1;j++) flg&=!adj(p[j],p[v]);
    for(int j=0;j<v;j++) flg&=(p[j]!=p[v]);
    for(int j=0;j<m;j++) flg&=(r[j]!=p[v]);
    if(flg) dfs2(v+1);
  }
}
signed main(){
  while(cin>>n,n){
    p.resize(n);
    for(int i=0;i<n;i++) cin>>p[i].X>>p[i].Y;
    cin>>m;
    r.resize(m);
    for(int i=0;i<m;i++) cin>>r[i].X>>r[i].Y;
    cin>>g.X>>g.Y;
    map<VP,int> mv[2];
    queue<VP> q;
    q.push(p);
    mv[0][p]=0;
    int ans=20;
    while(!q.empty()){
      p=q.front();q.pop();
      int d=mv[0][p];
      if(d>=10) break;
      t.clear();
      dfs(0,0);
      for(VP np:t){
	if(!mv[0].count(np)){
	  if(max(abs(np[0].X-g.X),abs(np[0].Y-g.Y))+d+1>=20) continue;
	  mv[0][np]=d+1;
	  q.push(np);
	}
      }
    }
  END:
    
    while(!q.empty()) q.pop();
    t.clear();
    dfs2(0);
    for(VP np:t){
      q.push(np);
      mv[1][np]=0;
    }
    while(!q.empty()){
      p=q.front();q.pop();
      int d=mv[1][p];
      if(d>=min(ans,9)) break;
      if(mv[0].count(p))
	ans=min(ans,mv[0][p]+mv[1][p]);
      t.clear();
      dfs(0,0);
      for(VP np:t){
	if(!mv[1].count(np)){
	  mv[1][np]=d+1;
	  q.push(np);
	  if(mv[0].count(np))
	    ans=min(ans,mv[0][np]+mv[1][np]);
	}
      }
    }
    cout<<ans<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 12550
memory_kb: 32244
final_rank: 18

code_snippet: #define _USE_MATH_DEFINES
#include <iostream>
#include <fstream>
#include<vector>
#include<algorithm>
#include<numeric>
#include<set>
#include<map>
#include<queue>
#include<functional>
using namespace std;
#define rep(i,n) for (auto i = 0; i < n; i++)
#define range(i,v) for (auto &i:v)
   
struct init{
    init(){
        cin.tie(0); ios::sync_with_stdio(false);
    }
}________init;
   
const int D = 7;
const int dr[] = { 0, 1, 1, 0, -1, -1 ,0};
const int dc[] = { -1, -1, 0, 1, 1, 0 ,0};
inline bool near(int pr, int pc, int qr, int qc){
    rep(i, D-1){
        if (pr + dr[i] == qr&&pc + dc[i] == qc)return true;
    }
    return false;
}
inline bool eq_near(int pr, int pc, int qr, int qc){
    rep(i, D){
        if (pr + dr[i] == qr&&pc + dc[i] == qc)return true;
    }
    return false;
}
   
typedef vector<int> V;
typedef vector<V> VV;
inline bool check(VV &snake, set<V> &stone){
    int n = snake.size();
    range(it, snake)if (stone.count(it))return false;
    rep(i, n){
        if (i + 1 < n){
            int j = i + 1;
            if (!near(snake[i][0], snake[i][1], snake[j][0], snake[j][1]))return false;
        }
        rep(j, n)if (i + 2 <= j){
            if (eq_near(snake[i][0], snake[i][1], snake[j][0], snake[j][1]))return false;
        }
    }
    return true;
   
}
   
inline bool check2(int n,VV &snake, set<V> &stone){
    if (stone.count(snake[n-1]))return false;
    {
        rep(k, 2){
            int i = n - k - 1;
            if (i>=0&&i + 1 < (int)snake.size()){
                int j = i + 1;
                if (!near(snake[i][0], snake[i][1], snake[j][0], snake[j][1]))return false;
            }
        }
        int i = n-1;
        rep(j, n-2){
            if (eq_near(snake[i][0], snake[i][1], snake[j][0], snake[j][1]))return false;
        }
    }
    return true;
}
map<VV, int> cost;
int main(){
    #ifdef INPUT_FROM_FILE
        ifstream cin("sample.in");
        ofstream cout("sample.out");
    #endif
    int n, k;
    while (cin >> n, n){
  
        set<V> stone;
        VV snake(n, V(2));
   
        range(jt, snake)range(it, jt)cin >> it;
   
           
        cin >> k;
cost.clear();
        cost[snake] = 0;
        rep(i, k){
            V s(2);
            range(it, s)cin >> it;
            stone.insert(s);
        }
        V goal(2);
        range(it, goal)cin >> it;
        queue<VV> que;
        que.push(snake);
        while (!que.empty()){
            auto v = que.front();
            que.pop();
            //printf("%d\n", cost[v]);
            if (v[0] == goal){
                cout << cost[v] << endl;
                break;
            }
            auto u = v;
            std::function<void(int, bool)> dfs = [&](int k, bool prev_move){
                if (k == n){
                    if (cost.count(u) == 0)
if(20>=cost[v]+1+max(abs(u[0][0]-goal[0]),abs(u[0][1]-goal[1]))){
                        cost[u] = cost[v] + 1;
                        que.push(u);
                    }
                }
                else
                if (prev_move){
                    dfs(k + 1, false);
                }
                else
                    rep(i, D){
                        u[k][0] += dr[i];
                        u[k][1] += dc[i];
                        if(check2(k+1,u, stone))dfs(k + 1, i != D - 1);
                        u[k][0] -= dr[i];
                        u[k][1] -= dc[i];
                    }
            };
            dfs(0, false);
        };
    }
       
    return 0;
}
accuracy: 1
time_ms: 5070
memory_kb: 39164
final_rank: 12