Problem:
Problem G:
Traffic
You are a resident of Kyoot (oh, well, it’s not a misspelling!) city. All streets there are neatly built on a
grid; some streets run in a meridional (north-south) direction and others in a zonal (east-west) direction.
The streets that run from north to south are called avenues, whereas those which run from east to west
are called
drives
.
Every avenue and drive in the city is numbered to distinguish one from another. The westernmost avenue
is called the
1st avenue
. The avenue which lies next to the
1st avenue
is the
2nd avenue
, and so forth.
Similarly, drives are numbered from south to north. The figure below illustrates this situation.
Figure 1: The Road Map of the Kyoot City
There is an intersection with traffic signals to regulate traffic on each crossing point of an avenue and a
drive. Each traffic signal in this city has two lights. One of these lights is colored green, and means “you
may go”. The other is red, and means “you must stop here”. If you reached an intersection during the
red light (including the case where the light turns to red on your arrival), you must stop and wait there
until the light turns to green again. However, you do not have to wait in the case where the light has
just turned to green when you arrived there.
Traffic signals are controlled by a computer so that the lights for two different directions always show
different colors. Thus if the light for an avenue is green, then the light for a drive must be red, and vice
versa. In order to avoid car crashes, they will never be green together. Nor will they be red together, for efficiency. So all the signals at one intersection turn simultaneously; no sooner does one signal turn to
red than the other turns to green. Each signal has a prescribed time interval and permanently repeats
the cycle.
Figure 2: Signal and Intersection
By the way, you are planning to visit your friend by car tomorrow. You want to see her as early as
possible, so you are going to drive through the shortest route. However, due to existence of the traffic
signals, you cannot easily figure out which way to take (the city also has a very sophisticated camera
network to prevent crime or violation: the police would surely arrest you if you didn’t stop on the red
light!). So you decided to write a program to calculate the shortest possible time to her house, given the
town map and the configuration of all traffic signals.
Your car runs one unit distance in one unit time. Time needed to turn left or right, to begin moving,
and to stop your car is negligible. You do not need to take other cars into consideration.
Input
The input consists of multiple test cases. Each test case is given in the format below:
w h
d
A,1
d
A,2
. . . d
A,w−1
d
D,1
d
D,2
. . . d
D,h−1
ns
1,1
ew
1,1
s
1,1
.
.
.
ns
w,1
ew
w,1
s
w,1
ns
1,2
ew
1,2
s
1,2
.
.
.
ns
w,h
ew
w,h
s
w,h
x
s
y
s
x
d
y
d
Two integers w and h (2 ≤
w
,
h
≤ 100) in the first line indicate the number of avenues and drives in the
city, respective
...(truncated)

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 105

enum DIR{
	yoko,
	tate,
};

enum Type{
	Green,
	Red,
};

struct Edge{
	Edge(int arg_to,int arg_dist,bool arg_is_yoko){
		to = arg_to;
		dist = arg_dist;
		is_yoko = arg_is_yoko;
	}

	int to,dist;
	bool is_yoko;
};

struct Info{

	int a,b;
	bool is_yoko;
};

struct State{

	State(){
		node = sum_dist = 0;
		type = Green;
		dir = yoko;
		is_goal = false;
	}

	State(int arg_node,int arg_sum_dist,Type arg_type,DIR arg_dir,bool arg_is_goal){
		node = arg_node;
		sum_dist = arg_sum_dist;
		type = arg_type;
		dir = arg_dir;
		is_goal = arg_is_goal;
	}
	bool operator<(const struct State& arg) const{

		return sum_dist > arg.sum_dist; //昇順(PQ)
	}
	int node,sum_dist;
	Type type;
	DIR dir;
	bool is_goal;
};


vector<Edge> G[SIZE*SIZE];

int W,H;
int D_yoko[SIZE],D_tate[SIZE];
int NS[SIZE*SIZE],EW[SIZE*SIZE],S[SIZE*SIZE];
int X[SIZE*SIZE],Y[SIZE*SIZE];

int min_dist[SIZE*SIZE][2][2];


int getInd(int row,int col){

	return row*W + col;
}

//通りの計算
Info calcPos(int x,int y){

	Info ret;
	ret.a = -1;
	ret.b = -1;

	int h = 0,w = 0;

	//横方向の通り
	for(int row = 0; row < H; row++){
		if(y != h){

			h += D_tate[row];
			continue;
		}

		w = 0;
		for(int col = 0; col < W; col++){
			if(x > w && x < w+D_yoko[col]){

				ret.a = getInd(row,col);
				ret.b = getInd(row,col+1);
				ret.is_yoko = true;
				return ret;
			}
			w += D_yoko[col];
		}
		h += D_tate[row];
	}

	//縦方向の通り
	w = 0;
	for(int col = 0; col < W; col++){
		if(x != w){

			w += D_yoko[col];
			continue;
		}

		h = 0;
		for(int row = 0; row < H; row++){
			if(y > h && y < h+D_tate[row]){

				ret.a = getInd(row,col);
				ret.b = getInd(row+1,col);
				ret.is_yoko = false;
				return ret;
			}
			h += D_tate[row];
		}
		w += D_yoko[col];
	}

	return ret; //バグ
}

//ある時刻における信号機の色を計算
Type calcColor(int ind,int T,bool is_yoko){

	int base = NS[ind]+EW[ind];

	int mod = T%base;

	if(S[ind] == 0){ //最初に南北方向の信号が緑

		if(is_yoko){ //左右の移動

			//■到着した瞬間に緑は待たなくてよい
			if(mod < NS[ind]){

				return Red;
			}else{

				return Green;
			}

		}else{ //南北の移動

			//■到着した瞬間に赤は停止
			if(mod < NS[ind]){

				return Green;
			}else{

				return Red;
			}
		}

	}else{ //最初に東西方向の信号が緑

		if(is_yoko){ //東西の移動

			//■到着した瞬間に赤は停止
			if(mod < EW[ind]){

				return Green;

			}else{

				return Red;
			}

		}else{ //南北の移動

			//■到着した瞬間に緑は待たなくてよい
			if(mod < EW[ind]){

				return Red;

			}else{

				return Green;
			}
		}
	}
}

void func(){

	for(int i = 0; i < H*W; i++){
		G[i].clear();
	}

	//区画幅(横)
	for(int i = 0; i < W-1; i++){

		scanf("%d",&D_yoko[i]);
	}
	//区画幅(縦)
	for(int i = 0; i < H-1; i++){

		scanf("%d",&D_tate[i]);
	}

	//H*W個の交差点の座標を計算
	int h = 0;
	for(int row = 0; row < H; row++){
		int w = 0;
		for(int col = 0; col < W; col++){
			int ind = getInd(row,col);
			X[ind] = w;
			Y[ind] = h;
			w += D_yoko[col];
		}
		h += D_tate[row];
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){

			int ind = getInd(row,col);

			scanf("%d %d %d",&NS[ind],&EW[ind],&S[ind]);
		}
	}

	int s_x,s_y;
	scanf("%d %d",&s_x,&s_y);

	Info s_pos = calcPos(s_x,s_y);

	int t_x,t_y;
	scanf("%d %d",&t_x,&t_y);

	Info t_pos = calcPos(t_x,t_y);


	//同じ通りにある
	if(s_pos.a == t_pos.a && s_pos.b == t_pos.b){

		if(s_x == t_x){

			printf("%d\n",abs(s_y-t_y));
			return;

		}else{

			printf("%d\n",abs(s_x-t_x));
			return;
		}
	}

	/*辺張り*/

	//左右
	for(int row = 0; row < H; row++){
		for(int col = 0; col < W-1; col++){

			int a = getInd(row,col);
			int b = getInd(row,col+1);

			G[a].push_back(Edge(b,D_yoko[col],true));
			G[b].push_back(Edge(a,D_yoko[col],true));
		}
	}

	//上下
	for(int col = 0; col < W; col++){
		for(int row = 0; row < H-1; row++){

			int a = getInd(row,col);
			int b = getInd(row+1,col);

			G[a].push_back(Edge(b,D_tate[row],false));
			G[b].push_back(Edge(a,D_tate[row],false));
		}
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			for(int a = 0; a < 2 ; a++){

				int ind = getInd(row,col);
				min_dist[ind][Green][a] = BIG_NUM;
				min_dist[ind][Red][a] = BIG_NUM;
			}
		}
	}

	priority_queue<State> Q;

	/* とりあえず、スタートから最寄りの交差点に寄る */

	if(s_pos.is_yoko){

		//aへ
		int T = abs(s_x - X[s_pos.a]);
		Type type = calcColor(s_pos.a,T,true);

		Q.push(State(s_pos.a,T,type,yoko,false));

		//bへ
		T = abs(s_x - X[s_pos.b]);
		type = calcColor(s_pos.b,T,true);

		Q.push(State(s_pos.b,T,type,yoko,false));

	}else{ //startが縦の通りにある

		//aへ
		int T = abs(s_y - Y[s_pos.a]);
		Type type = calcColor(s_pos.a,T,false);

		Q.push(State(s_pos.a,T,type,tate,false));

		//bへ
		T = abs(s_y - Y[s_pos.b]);
		type = calcColor(s_pos.b,T,false);

		Q.push(State(s_pos.b,T,type,tate,false));
	}

	while(!Q.empty()){

		State state = Q.top();
		Q.pop();

		if(state.is_goal){

			printf("%d\n",state.sum_dist);
			return;
		}

		if(state.sum_dist > min_dist[state.node][state.type][state.dir]){

			continue;
		}
		if(state.type == Red){

			bool is_yoko = (state.dir == yoko);

			//青になるまで待つ
			int add = 0;
			int base = NS[state.node]+EW[state.node];
			int now = state.sum_dist%base;

			if(is_yoko){

				if(S[state.node] == 0){ //最初に南北が青

					add = NS[state.node]-now;

				}else{ //最初に東西が青

					add = base-now;

				}

			}else{  //南北の動き

				if(S[state.node] == 0){ //最初に南北が青

					add = base-now;

				}else{ //最初に東西が青

					add = EW[state.node]-now;
				}
			}


			int next_node = state.node;
			int next_dist = state.sum_dist+add;
			DIR next_dir = state.dir;
			Type next_type = Green;

			if(min_dist[next_node][next_type][next_dir] > next_dist){

				min_dist[next_node][next_type][next_dir] = next_dist;
				Q.push(State(next_node,next_dist,next_type,next_dir,false));
			}
			continue;
		}

		for(int i = 0; i < G[state.node].size(); i++){

			int next_node = G[state.node][i].to;
			int next_dist = state.sum_dist + G[state.node][i].dist;


			//途中にゴールがあるか
			int a = min(state.node,next_node);
			int b = max(state.node,next_node);

			if(t_pos.a == a && t_pos.b == b){

				int add = abs(X[state.node]-t_x)+abs(Y[state.node]-t_y);
				int candidate = state.sum_dist+add;

				Q.push(State(state.node,candidate,state.type,state.dir,true)); //■■■■■■■■■これが最短とは限らないので1回push■■■■■■■■■

				continue;
			}

			Type next_type;
			DIR next_dir;


			if(G[state.node][i].is_yoko){ //左右

				next_type = calcColor(next_node,next_dist,true);
				next_dir = yoko;

			}else{ //上下

				next_type = calcColor(next_node,next_dist,false);
				next_dir = tate;
			}

			if(min_dist[next_node][next_type][next_dir] > next_dist){

				min_dist[next_node][next_type][next_dir] = next_dist;
				Q.push(State(next_node,next_dist,next_type,next_dir,false));
			}
		}
	}

	printf("-1\n"); //バグ
}


int main(){

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

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 300
memory_kb: 4424
final_rank: 5

code_snippet: #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<deque>
#include<algorithm>
#include<numeric>
#include<utility>
#include<complex>
#include<functional>
 
using namespace std;

/* constant */

const int MAX_W = 100;
const int MAX_H = 100;
const int MAX_HW = MAX_H * MAX_W;

const int INF = 1 << 30;

const int dxs[] = {  1,  0, -1,  0 };
const int dys[] = {  0,  1,  0, -1 };

/* typedef */

struct Signal {
  int nst, ewt, itv, s;
};

struct Stat {
  int d, pos, drc;
  Stat() {}
  Stat(int _d, int _pos, int _drc) { d = _d, pos = _pos, drc = _drc; }
  bool operator<(const Stat& st0) const { return d > st0.d; }
  void print() { printf("d=%d, pos=%d, drc=%d\n", d, pos, drc); }
};

enum { D_NS = 0, D_EW = 1 };

typedef vector<Stat> vs;

/* global variables */

int w, h, hw;
int dws[MAX_W], dhs[MAX_H];
Signal sgnls[MAX_HW + 2];

vs nbrs[MAX_HW + 2];
int dists[MAX_HW + 2][2];

/* subroutines */

void onroad(int x, int n, int *ds, int& i, int& dx) {
  i = 0, dx = x;
  while (i < n && dx >= ds[i]) dx -= ds[i], i++;
}

int time_go(Signal& sgnl, int t, int drc) {
  int rt = t % sgnl.itv;
  int tg = -1;
  
  if (sgnl.s == D_NS) {	// nst -> ewt
    if (drc == D_NS) tg = (rt < sgnl.nst) ? t : sgnl.itv * (t / sgnl.itv + 1);
    else tg = (rt >= sgnl.nst) ? t : (t / sgnl.itv) * sgnl.itv + sgnl.nst;
  }
  else {	// ewt -> nst
    if (drc == D_EW) tg = (rt < sgnl.ewt) ? t : sgnl.itv * (t / sgnl.itv + 1);
    else tg = (rt >= sgnl.ewt) ? t : (t / sgnl.itv) * sgnl.itv + sgnl.ewt;
  }

  return tg;
}

/* main */

int main() {
  for (;;) {
    cin >> w >> h;
    if (w == 0) break;

    hw = h * w;
    
    for (int i = 0; i < w - 1; i++) cin >> dws[i];
    for (int i = 0; i < h - 1; i++) cin >> dhs[i];

    for (int y = 0; y < h; y++)
      for (int x = 0; x < w; x++) {
	int pos = y * w + x;
	Signal& sgnl = sgnls[pos];
	cin >> sgnl.nst >> sgnl.ewt >> sgnl.s;
	sgnl.itv = sgnl.nst + sgnl.ewt;

	nbrs[pos].clear();

	for (int di = 0; di < 4; di++) {
	  int x0 = x + dxs[di];
	  int y0 = y + dys[di];
	  if (x0 >= 0 && x0 < w && y0 >= 0 && y0 < h) {
	    int pos0 = y0 * w + x0;
	    int ec, edrc;
	    if (x0 != x) {
	      ec = dws[(x0 < x) ? x0 : x];
	      edrc = D_EW;
	    }
	    else {
	      ec = dhs[(y0 < y) ? y0 : y];
	      edrc = D_NS;
	    }
	    nbrs[pos].push_back(Stat(ec, pos0, edrc));
	  }
	}
      }

    int sx, sy;
    cin >> sx >> sy;

    int sxi, syi, sdx, sdy;
    onroad(sx, w - 1, dws, sxi, sdx);
    onroad(sy, h - 1, dhs, syi, sdy);
    //printf("(sxi,syi)=(%d,%d), (sdx,sdy)=(%d,%d)\n", sxi, syi, sdx, sdy);
    
    nbrs[hw].clear();
    
    if (sdx != 0) {
      int pos0 = syi * w + sxi, pos1 = pos0 + 1;
      nbrs[hw].push_back(Stat(sdx, pos0, D_EW));
      nbrs[hw].push_back(Stat(dws[sxi] - sdx, pos1, D_EW));
      sgnls[hw].nst = 0;
      sgnls[hw].ewt = 1;
      sgnls[hw].itv = 1;
      sgnls[hw].s = D_EW;
    }
    else {
      int pos0 = syi * w + sxi, pos1 = pos0 + w;
      nbrs[hw].push_back(Stat(sdy, pos0, D_NS));
      nbrs[hw].push_back(Stat(dhs[syi] - sdy, pos1, D_NS));
      sgnls[hw].nst = 1;
      sgnls[hw].ewt = 0;
      sgnls[hw].itv = 1;
      sgnls[hw].s = D_NS;
    }

    int gx, gy;
    cin >> gx >> gy;

    int gxi, gyi, gdx, gdy;
    onroad(gx, w - 1, dws, gxi, gdx);
    onroad(gy, h - 1, dhs, gyi, gdy);
    //printf("(gxi,gyi)=(%d,%d), (gdx,gdy)=(%d,%d)\n", gxi, gyi, gdx, gdy);

    if (gdx != 0) {
      int pos0 = gyi * w + gxi, pos1 = pos0 + 1;
      nbrs[pos0].push_back(Stat(gdx, hw + 1, D_EW));
      nbrs[pos1].push_back(Stat(dws[gxi] - gdx, hw + 1, D_EW));
    }
    else {
      int pos0 = gyi * w + gxi, pos1 = pos0 + w;
      nbrs[pos0].push_back(Stat(gdy, hw + 1, D_NS));
      nbrs[pos1].push_back(Stat(dhs[gyi] - gdy, hw + 1, D_NS));
    }

    if (sxi == gxi && syi == gyi) {
      if (sdy == 0 && gdy == 0) {
	int dx = (gdx > sdx) ? gdx - sdx : sdx - gdx;
	nbrs[hw].push_back(Stat(dx, hw + 1, D_EW));
      }
      else if (sdx == 0 && gdx == 0) {
	int dy = (gdy > sdy) ? gdy - sdy : sdy - gdy;
	nbrs[hw].push_back(Stat(dy, hw + 1, D_NS));
      }
    }
    
    for (int pos = 0; pos < hw + 2; pos++)
      for (int drc = 0; drc < 2; drc++)
	dists[pos][drc] = INF;

    dists[hw][0] = dists[hw][1] = 0;

    priority_queue<Stat> q;
    q.push(Stat(0, hw, sgnls[hw].s));

    int mind = INF;
    
    while (! q.empty()) {
      Stat u = q.top();
      q.pop();
      //u.print();
      
      if (u.d != dists[u.pos][u.drc]) continue;
      if (u.pos == hw + 1) {
	mind = u.d;
	break;
      }

      int ud = time_go(sgnls[u.pos], u.d, u.drc);
      vs& nbru = nbrs[u.pos];

      for (vs::iterator vit = nbru.begin(); vit != nbru.end(); vit++) {
	Stat& v = *vit;
	int vd =  ud + v.d;

	if (dists[v.pos][v.drc] > vd) {
	  dists[v.pos][v.drc] = vd;
	  q.push(Stat(vd, v.pos, v.drc));
	}
      }
    }

    cout << mind << endl;
  }

  return 0;
}
accuracy: 1
time_ms: 460
memory_kb: 2304
final_rank: 1

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

const int INF = INT_MAX / 2;

int h, w;
vector<int> dy, dx;
vector<vector<int> > ns, ew, s;

void add(int& y, int& x)
{
    int y2 = 1;
    while(y > 0){
        y -= dy[y2];
        ++ y2;
    }
    int x2 = 1;
    while(x > 0){
        x -= dx[x2];
        ++ x2;
    }

    if(y != 0 || x != 0){
        if(y == 0){
            dx[x2-1] += x;
            dx.insert(dx.begin()+x2, -x);
            for(int i=0; i<h+2; ++i){
                ns[i].insert(ns[i].begin()+x2, 1);
                ew[i].insert(ew[i].begin()+x2, INF);
                s[i].insert(s[i].begin()+x2, 1);
            }
            ++ w;
        }else{
            dy[y2-1] += y;
            dy.insert(dy.begin()+y2, -y);
            ns.insert(ns.begin()+y2, vector<int>(w+2, INF));
            ew.insert(ew.begin()+y2, vector<int>(w+2, 1));
            s.insert(s.begin()+y2, vector<int>(w+2, 0));
            ++ h;
        }
    }

    y = y2;
    x = x2;
}

int main()
{
    for(;;){
        cin >> w >> h;
        if(h == 0)
            return 0;

        dx.assign(w+1, INF);
        dy.assign(h+1, INF);
        for(int i=1; i<w; ++i)
            cin >> dx[i];
        for(int i=1; i<h; ++i)
            cin >> dy[i];

        ns = ew = s = vector<vector<int> >(h+2, vector<int>(w+2, 1));
        for(int i=1; i<=h; ++i){
            for(int j=1; j<=w; ++j){
                cin >> ns[i][j] >> ew[i][j] >> s[i][j];
            }
        }

        int sy, sx, gy, gx;
        cin >> sx >> sy >> gx >> gy;
        int sy0 = sy;
        int sx0 = sx;
        add(sy0, sx0);
        add(gy, gx);
        add(sy, sx);

        vector<vector<vector<int> > > dp(h+2, vector<vector<int> >(w+2, vector<int>(2, INF)));
        for(int i=0; i<h+2; ++i)
            dp[i][0][1] = dp[i][w+1][1] = -1;
        for(int i=0; i<w+2; ++i)
            dp[0][i][0] = dp[h+1][i][0] = -1;

        multimap<int, pair<pair<int, int>, int> > mm;
        dp[sy][sx][0] = dp[sy][sx][1] = 0;
        mm.insert(make_pair(0, make_pair(make_pair(sy, sx), 0)));
        mm.insert(make_pair(0, make_pair(make_pair(sy, sx), 1)));

        while(!mm.empty()){
            int t = mm.begin()->first;
            int y = mm.begin()->second.first.first;
            int x = mm.begin()->second.first.second;
            int d = mm.begin()->second.second;
            mm.erase(mm.begin());
            if(t > dp[y][x][d])
                continue;

            if(s[y][x] == 0){
                int t2 = t % (ns[y][x] + ew[y][x]);
                if(d == 0){
                    if(t2 >= ns[y][x])
                        t += -t2 + (ns[y][x] + ew[y][x]);
                }else{
                    if(t2 < ns[y][x])
                        t += -t2 + ns[y][x];
                }
            }else{
                int t2 = t % (ew[y][x] + ns[y][x]);
                if(d == 0){
                    if(t2 < ew[y][x])
                        t += -t2 + ew[y][x];
                }else{
                    if(t2 >= ew[y][x])
                        t += -t2 + (ew[y][x] + ns[y][x]);
                }
            }

            if(y == gy && x == gx && t < INF){
                cout << t << endl;
                break;
            }

            for(int i=0; i<2; ++i){
                int t2 = t + dy[y-1+i];
                int y2 = y - 1 + 2*i;
                int x2 = x;
                int d2 = 0;
                if(t2 < dp[y2][x2][d2]){
                    dp[y2][x2][d2] = t2;
                    mm.insert(make_pair(t2, make_pair(make_pair(y2, x2), d2)));
                }
            }
            for(int i=0; i<2; ++i){
                int t2 = t + dx[x-1+i];
                int y2 = y;
                int x2 = x - 1 + 2*i;
                int d2 = 1;
                if(t2 < dp[y2][x2][d2]){
                    dp[y2][x2][d2] = t2;
                    mm.insert(make_pair(t2, make_pair(make_pair(y2, x2), d2)));
                }
            }
        }
    }
}
accuracy: 1
time_ms: 580
memory_kb: 2064
final_rank: 2

code_snippet: #include<iostream>
#include<cassert>
#include<climits>
#include<queue>
#include<vector>
#include<complex>
#include<cmath>
#include<algorithm>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define pb         push_back
#define NODE(i,j,c)  ((i)*c+(j)+2)
#define ALL(C)      (C).begin(),(C).end()
typedef long long ll;
typedef complex<double> P;

const ll inf = (1LL)<<60;

enum{N=0,E=1,S=0,W=1};
enum{VER=0,HOR=1};//HOR- VER|
char dir[]={"NESW"};

ll check(ll t,int dir,int s,int n,int e){//need to take dir%2
dir%=2;
  if (n+e==0)return 0;
  ll mod=n+e;
  ll tmp=t%mod;
  if (s==VER){
    if (tmp <n){
      if (dir==HOR)return n-tmp;
      else if (dir==VER)return 0;
    }else {
      if (dir==HOR)return 0;
      else if (dir==VER)return n+e-tmp;
    }
  }else if (s == HOR){
    if (tmp < e){
      if (dir==VER)return e-tmp;
      else if (dir==HOR)return 0;
    }else {
      if (dir==HOR)return e+n-tmp;
      else if (dir==VER)return 0;
    }
  }
  return -1;
}

class state{
public:
  short now,dir;
  ll cost;
  bool operator<(const state&a)const{
    return cost > a.cost;
  }
};

typedef struct{int to,dir;int cost;}Edge;

const int node =100*100+2;
ll cost[node][4];
vector<Edge> edge[node];
int  es[node];
int  ns[node];
int  s[node];

ll dijkstra(int n){//src==0,dst==1
  rep(i,n)rep(j,4)cost[i][j]=inf;
  priority_queue<state> Q;
  rep(i,edge[0].size()){
    int nex=edge[0][i].to;
    int ned=edge[0][i].dir;
    cost[nex][ned]=edge[0][i].cost;
    cost[nex][ned]+=check(cost[nex][ned],ned,s[nex],ns[nex],es[nex]);
    Q.push((state){nex,ned,cost[nex][ned]});
  }

  while(!Q.empty()){
    state now = Q.top();Q.pop();
    if (cost[now.now][now.dir] != now.cost)continue;
    if (now.now == 1)return now.cost;

    rep(i,edge[now.now].size()){
      int nex=edge[now.now][i].to;
      int ned=edge[now.now][i].dir;
      ll  tcost=now.cost+edge[now.now][i].cost;
      tcost+=check(tcost,ned,s[nex],ns[nex],es[nex]);
      if (tcost < cost[nex][ned]){
	cost[nex][ned]=tcost;
	Q.push((state){nex,ned,tcost});
      }
    }
  }
  return -1;
}

bool isp(double x1,double y1,double x2,double y2,double x3,double y3){
  P a(x1,y1),b(x2,y2),c(x3,y3);
  return abs(a-c)+abs(b-c) < abs(a-b)+1e-10;
}

int getindex(int a,vector<int> &b){
  rep(i,b.size()-1){
    if (b[i] <= a && a <= b[i+1])return i;
  }
}

void setpos(int cur,int xs,int ys,vector<int> &x,vector<int> &y){
  int r=y.size(),c=x.size();
  rep(i,x.size()){
    if (xs == x[i]){
      int tmp=getindex(ys,y);
      edge[cur].pb((Edge){NODE(tmp+1,i,c),N,y[tmp+1]-ys});
      edge[NODE(tmp+1,i,c)].pb((Edge){cur,S,y[tmp+1]-ys});
      edge[cur].pb((Edge){NODE(tmp,i,c)  ,S,ys-y[tmp]});
      edge[NODE(tmp,i,c)].pb((Edge){cur,N,ys-y[tmp]});
    }
  }

  rep(i,y.size()){
    if (ys == y[i]){
      int tmp=getindex(xs,x);
      edge[cur].pb((Edge){NODE(i,tmp+1,c),E,x[tmp+1]-xs});
      edge[NODE(i,tmp+1,c)].pb((Edge){cur,W,x[tmp+1]-xs});
      edge[cur].pb((Edge){NODE(i,tmp,c  ),W,xs-x[tmp]});
      edge[NODE(i,tmp,c)].pb((Edge){cur  ,E,xs-x[tmp]});
    }
  }
}

int issame(int a,int b,vector<int> &cor,vector<int>&c,int cd){
  bool isok=false;
  rep(i,c.size()){
    if (c[i] == cd)isok=true;
  }
  if (!isok)return -1;
  rep(i,cor.size()-1){
    if (cor[i] <= a && a <= cor[i+1] &&
	cor[i] <= b && b <= cor[i+1])return abs(a-b);
  }
  return -1;
}

main(){
  int r,c;
  while(cin>>c>>r && r){
    vector<int> x(c,0),y(r,0);
    REP(i,1,c)cin>>x[i],x[i]+=x[i-1];
    REP(i,1,r)cin>>y[i],y[i]+=y[i-1];
    rep(i,r*c+2)edge[i].clear();

    rep(i,r){
      rep(j,c){
	int cur=NODE(i,j,c),nex;
	ll dist;
	if (i){
	  nex=NODE(i-1,j,c);dist=y[i]-y[i-1];
	  edge[cur].pb((Edge){nex,S,dist});
	}
	if (i+1!=r){
	  nex=NODE(i+1,j,c);dist=y[i+1]-y[i];
	  edge[cur].pb((Edge){nex,N,dist});
	}
	if (j){
	  nex=NODE(i,j-1,c);dist=x[j]-x[j-1];
	  edge[cur].pb((Edge){nex,W,dist});
	}
	if (j+1!=c){
	  nex=NODE(i,j+1,c);dist=x[j+1]-x[j];
	  edge[cur].pb((Edge){nex,E,dist});
	}
      }
    }

    rep(i,r){
      rep(j,c)cin>>ns[NODE(i,j,c)]>>es[NODE(i,j,c)]>>s[NODE(i,j,c)];
    }

    int xs,ys,xd,yd;
    cin>>xs>>ys>>xd>>yd;
    
    setpos(0,xs,ys,x,y);
    setpos(1,xd,yd,x,y);
    if (xs == xd && ys == yd){
      cout << 0 << endl;
      continue;
    }
    if (xs==xd){
      ll tmp=issame(ys,yd,y,x,xs);
      if (tmp != -1){cout << tmp << endl;continue;}
    }
    if (ys==yd){
      ll tmp=issame(xs,xd,x,y,ys);
      if (tmp != -1){cout << tmp << endl;continue;}
    }
    cout << dijkstra(r*c+2) << endl;
  }
  return false;
}
accuracy: 1
time_ms: 920
memory_kb: 2020
final_rank: 3

code_snippet: #include<iostream>
#include<cassert>
#include<climits>
#include<queue>
#include<vector>
#include<complex>
#include<cmath>
#include<algorithm>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define pb         push_back
#define NODE(i,j,c)  ((i)*c+(j)+2)
#define ALL(C)      (C).begin(),(C).end()
typedef long long ll;
typedef complex<double> P;

const ll inf = (1LL)<<60;

enum{N=0,E=1,S=0,W=1};
enum{VER=0,HOR=1};//HOR- VER|
char dir[]={"NESW"};

ll check(ll t,int dir,int s,int n,int e){//need to take dir%2
  if (n+e==0)return 0;
  ll mod=n+e;
  ll tmp=t%mod;
  if (s==VER){
    if (tmp <n){
      if (dir==HOR)return n-tmp;
      else if (dir==VER)return 0;
    }else {
      if (dir==HOR)return 0;
      else if (dir==VER)return n+e-tmp;
    }
  }else if (s == HOR){
    if (tmp < e){
      if (dir==VER)return e-tmp;
      else if (dir==HOR)return 0;
    }else {
      if (dir==HOR)return e+n-tmp;
      else if (dir==VER)return 0;
    }
  }
  return -1;
}

class state{
public:
  short now,dir;
  ll cost;
  bool operator<(const state&a)const{
    return cost > a.cost;
  }
};

typedef struct{int to,dir;int cost;}Edge;

const int node =100*100+2;
ll cost[node][4];
vector<Edge> edge[node];
int  es[node];
int  ns[node];
int  s[node];

ll dijkstra(int n){//src==0,dst==1
  rep(i,n)rep(j,4)cost[i][j]=inf;
  priority_queue<state> Q;
  rep(i,edge[0].size()){
    int nex=edge[0][i].to;
    int ned=edge[0][i].dir;
    cost[nex][ned]=edge[0][i].cost;
    cost[nex][ned]+=check(cost[nex][ned],ned,s[nex],ns[nex],es[nex]);
    Q.push((state){nex,ned,cost[nex][ned]});
  }

  while(!Q.empty()){
    state now = Q.top();Q.pop();
    if (cost[now.now][now.dir] != now.cost)continue;
    if (now.now == 1)return now.cost;

    rep(i,edge[now.now].size()){
      int nex=edge[now.now][i].to;
      int ned=edge[now.now][i].dir;
      ll  tcost=now.cost+edge[now.now][i].cost;
      tcost+=check(tcost,ned,s[nex],ns[nex],es[nex]);
      if (tcost < cost[nex][ned]){
	cost[nex][ned]=tcost;
	Q.push((state){nex,ned,tcost});
      }
    }
  }
  return -1;
}

bool isp(double x1,double y1,double x2,double y2,double x3,double y3){
  P a(x1,y1),b(x2,y2),c(x3,y3);
  return abs(a-c)+abs(b-c) < abs(a-b)+1e-10;
}

int getindex(int a,vector<int> &b){
  rep(i,b.size()-1){
    if (b[i] <= a && a <= b[i+1])return i;
  }
}

void setpos(int cur,int xs,int ys,vector<int> &x,vector<int> &y){
  int r=y.size(),c=x.size();
  rep(i,x.size()){
    if (xs == x[i]){
      int tmp=getindex(ys,y);
      edge[cur].pb((Edge){NODE(tmp+1,i,c),N,y[tmp+1]-ys});
      edge[NODE(tmp+1,i,c)].pb((Edge){cur,S,y[tmp+1]-ys});
      edge[cur].pb((Edge){NODE(tmp,i,c)  ,S,ys-y[tmp]});
      edge[NODE(tmp,i,c)].pb((Edge){cur,N,ys-y[tmp]});
    }
  }

  rep(i,y.size()){
    if (ys == y[i]){
      int tmp=getindex(xs,x);
      edge[cur].pb((Edge){NODE(i,tmp+1,c),E,x[tmp+1]-xs});
      edge[NODE(i,tmp+1,c)].pb((Edge){cur,W,x[tmp+1]-xs});
      edge[cur].pb((Edge){NODE(i,tmp,c  ),W,xs-x[tmp]});
      edge[NODE(i,tmp,c)].pb((Edge){cur  ,E,xs-x[tmp]});
    }
  }
}

int issame(int a,int b,vector<int> &cor,vector<int>&c,int cd){
  bool isok=false;
  rep(i,c.size()){
    if (c[i] == cd)isok=true;
  }
  if (!isok)return -1;
  rep(i,cor.size()-1){
    if (cor[i] <= a && a <= cor[i+1] &&
	cor[i] <= b && b <= cor[i+1])return abs(a-b);
  }
  return -1;
}

main(){
  int r,c;
  while(cin>>c>>r && r){
    vector<int> x(c,0),y(r,0);
    REP(i,1,c)cin>>x[i],x[i]+=x[i-1];
    REP(i,1,r)cin>>y[i],y[i]+=y[i-1];
    rep(i,r*c+2)edge[i].clear();

    rep(i,r){
      rep(j,c){
	int cur=NODE(i,j,c),nex;
	ll dist;
	if (i){
	  nex=NODE(i-1,j,c);dist=y[i]-y[i-1];
	  edge[cur].pb((Edge){nex,S,dist});
	}
	if (i+1!=r){
	  nex=NODE(i+1,j,c);dist=y[i+1]-y[i];
	  edge[cur].pb((Edge){nex,N,dist});
	}
	if (j){
	  nex=NODE(i,j-1,c);dist=x[j]-x[j-1];
	  edge[cur].pb((Edge){nex,W,dist});
	}
	if (j+1!=c){
	  nex=NODE(i,j+1,c);dist=x[j+1]-x[j];
	  edge[cur].pb((Edge){nex,E,dist});
	}
      }
    }

    rep(i,r){
      rep(j,c)cin>>ns[NODE(i,j,c)]>>es[NODE(i,j,c)]>>s[NODE(i,j,c)];
    }

    int xs,ys,xd,yd;
    cin>>xs>>ys>>xd>>yd;
    
    setpos(0,xs,ys,x,y);
    setpos(1,xd,yd,x,y);
    if (xs == xd && ys == yd){
      cout << 0 << endl;
      continue;
    }
    if (xs==xd){
      ll tmp=issame(ys,yd,y,x,xs);
      if (tmp != -1){cout << tmp << endl;continue;}
    }
    if (ys==yd){
      ll tmp=issame(xs,xd,x,y,ys);
      if (tmp != -1){cout << tmp << endl;continue;}
    }
    cout << dijkstra(r*c+2) << endl;
  }
  return false;
}
accuracy: 1
time_ms: 920
memory_kb: 2020
final_rank: 3

code_snippet: #include<iostream>
#include<cassert>
#include<climits>
#include<queue>
#include<vector>
#include<complex>
#include<cmath>
#include<algorithm>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define pb         push_back
#define NODE(i,j,c)  ((i)*c+(j)+2)
#define ALL(C)      (C).begin(),(C).end()
typedef long long ll;
typedef complex<double> P;

const ll inf = (1LL)<<60;

enum{N=0,E=1,S=0,W=1};
enum{VER=0,HOR=1};//HOR- VER|
char dir[]={"NESW"};

ll check(ll t,int dir,int s,int n,int e){//need to take dir%2
  if (n+e==0)return 0;
  ll mod=n+e;
  ll tmp=t%mod;
  if (s==VER){
    if (tmp <n){
      if (dir==HOR)return n-tmp;
      else if (dir==VER)return 0;
    }else {
      if (dir==HOR)return 0;
      else if (dir==VER)return n+e-tmp;
    }
  }else if (s == HOR){
    if (tmp < e){
      if (dir==VER)return e-tmp;
      else if (dir==HOR)return 0;
    }else {
      if (dir==HOR)return e+n-tmp;
      else if (dir==VER)return 0;
    }
  }
  return -1;
}

class state{
public:
  short now,dir;
  ll cost;
  bool operator<(const state&a)const{
    return cost > a.cost;
  }
};

typedef struct{int to,dir;int cost;}Edge;

const int node =100*100+2;
ll cost[node][4];
vector<Edge> edge[node];
int  es[node];
int  ns[node];
int  s[node];

ll dijkstra(int n){//src==0,dst==1
  rep(i,n)rep(j,4)cost[i][j]=inf;
  priority_queue<state> Q;
  rep(i,edge[0].size()){
    int nex=edge[0][i].to;
    int ned=edge[0][i].dir;
    cost[nex][ned]=edge[0][i].cost;
    cost[nex][ned]+=check(cost[nex][ned],ned,s[nex],ns[nex],es[nex]);
    Q.push((state){nex,ned,cost[nex][ned]});
  }

  while(!Q.empty()){
    state now = Q.top();Q.pop();
    if (cost[now.now][now.dir] != now.cost)continue;
    if (now.now == 1)return now.cost;
    //    assert(cost[now.now][now.dir] >=0);
    //    cout << now.now <<" " << dir[now.dir] <<" " << now.cost << endl;

    rep(i,edge[now.now].size()){
      int nex=edge[now.now][i].to;
      int ned=edge[now.now][i].dir;
      ll  tcost=now.cost+edge[now.now][i].cost;
      //ll check(ll t,int dir,int s,int n,int e){//need to take dir%2
      //      cout << now.now <<" " << nex <<" " << check(tcost,ned,s[nex],ns[nex],es[nex])<<endl;
      tcost+=check(tcost,ned,s[nex],ns[nex],es[nex]);
      if (tcost < cost[nex][ned]){
	cost[nex][ned]=tcost;
	Q.push((state){nex,ned,tcost});
      }
    }
  }
  return -1;
}

bool isp(double x1,double y1,double x2,double y2,double x3,double y3){
  P a(x1,y1),b(x2,y2),c(x3,y3);
  return abs(a-c)+abs(b-c) < abs(a-b)+1e-10;
}

int getindex(int a,vector<int> &b){
  rep(i,b.size()-1){
    if (b[i] <= a && a <= b[i+1])return i;
  }
  assert(false);
}

void setpos(int cur,int xs,int ys,vector<int> &x,vector<int> &y){
  int r=y.size(),c=x.size();
  rep(i,x.size()){
    if (xs == x[i]){
      int tmp=getindex(ys,y);
      edge[cur].pb((Edge){NODE(tmp+1,i,c),N,y[tmp+1]-ys});
      edge[NODE(tmp+1,i,c)].pb((Edge){cur,S,y[tmp+1]-ys});
      edge[cur].pb((Edge){NODE(tmp,i,c)  ,S,ys-y[tmp]});
      edge[NODE(tmp,i,c)].pb((Edge){cur,N,ys-y[tmp]});
    }
  }

  rep(i,y.size()){
    if (ys == y[i]){
      int tmp=getindex(xs,x);
      edge[cur].pb((Edge){NODE(i,tmp+1,c),E,x[tmp+1]-xs});
      edge[NODE(i,tmp+1,c)].pb((Edge){cur,W,x[tmp+1]-xs});
      edge[cur].pb((Edge){NODE(i,tmp,c  ),W,xs-x[tmp]});
      edge[NODE(i,tmp,c)].pb((Edge){cur  ,E,xs-x[tmp]});
    }
  }
}

int issame(int a,int b,vector<int> &cor,vector<int>&c,int cd){
  bool isok=false;
  rep(i,c.size()){
    if (c[i] == cd)isok=true;
  }
  if (!isok)return -1;
  rep(i,cor.size()-1){
    if (cor[i] <= a && a <= cor[i+1] &&
	cor[i] <= b && b <= cor[i+1])return abs(a-b);
  }
  return -1;
}

main(){
  int r,c;
  while(cin>>c>>r && r){
    vector<int> x(c,0),y(r,0);
    REP(i,1,c)cin>>x[i],x[i]+=x[i-1];
    REP(i,1,r)cin>>y[i],y[i]+=y[i-1];
    rep(i,r*c+2)edge[i].clear();

    rep(i,r){
      rep(j,c){
	int cur=NODE(i,j,c),nex;
	ll dist;
	if (i){
	  nex=NODE(i-1,j,c);dist=y[i]-y[i-1];
	  edge[cur].pb((Edge){nex,S,dist});
	}
	if (i+1!=r){
	  nex=NODE(i+1,j,c);dist=y[i+1]-y[i];
	  edge[cur].pb((Edge){nex,N,dist});
	}
	if (j){
	  nex=NODE(i,j-1,c);dist=x[j]-x[j-1];
	  edge[cur].pb((Edge){nex,W,dist});
	}
	if (j+1!=c){
	  nex=NODE(i,j+1,c);dist=x[j+1]-x[j];
	  edge[cur].pb((Edge){nex,E,dist});
	}
      }
    }

    rep(i,r){
      rep(j,c)cin>>ns[NODE(i,j,c)]>>es[NODE(i,j,c)]>>s[NODE(i,j,c)];
    }

    int xs,ys,xd,yd;
    cin>>xs>>ys>>xd>>yd;
    
    setpos(0,xs,ys,x,y);
    setpos(1,xd,yd,x,y);
    if (xs == xd && ys == yd){
      cout << 0 << endl;
      continue;
    }
    if (xs==xd){
      ll tmp=issame(ys,yd,y,x,xs);
      if (tmp != -1){cout << tmp << endl;continue;}
    }
    if (ys==yd){
      ll tmp=issame(xs,xd,x,y,ys);
      if (tmp != -1){cout << tmp << endl;continue;}
    }
    cout << dijkstra(r*c+2) << endl;

//      rep(i,x.size())cout << x[i]<<" ";cout <<endl;
//      rep(i,y.size())cout<<y[i]<<" ";cout << endl;
//      rep(i,r*c+2){
//        cout << "now ";
//        if (i == 0)cout <<0 <<"(" << xs <<"," << ys <<")";
//        else if (i == 1)cout << 1 <<"(" << xd <<"," << yd <<")";
//        else cout <<i <<"(" <<  x[(i-2)%c] <<"," << y[(i-2)/c] << ")";
//        cout << endl;
//        rep(j,edge[i].size()){
//  	cout << edge[i][j].to<<" " ;
//  	if (edge[i][j].to==0)cout << xs <<" " << ys <<" ";
//  	else if(edge[i][j].to == 1)cout <<xd <<" " << yd <<" ";
//  	else cout << "(" << x[(edge[i][j].to-2)%c] <<"," << y[(edge[i][j].to-2)/c] <<")";
//  	cout << edge[i][j].cost <<" " << dir[edge[i][j].dir] << endl;
//        }
//        cout << endl;
//      }

  }
  return false;
}
accuracy: 1
time_ms: 930
memory_kb: 2016
final_rank: 5