#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;
}



Measured memory_bytes: 52028