#include<iostream>
#include<cstdio>
#include <queue>
#include<cmath>
#include <cstdlib>
#include <algorithm>
#include<vector>
#include<sstream>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
int dx[] = {-1,1,0,0};
int dy[] = {0,0,-1,1};
struct P{
	int x,y;
	P(int a,int b){x = a, y = b;}
	P(){};
};
bool operator<(const P &a,const P &b){
	if(a.x == b.x)return a.y < b.y;
	return a.x < b.x;
}
P get(string to){
	rep(i,to.size())if(to[i] == '-')to[i] = ' ';
	stringstream ss(to);
	pair<int,int> ret;
	char a;int b;
	ss >> a >> b;
	return P(b-1,a-'a');
}
struct NODE{
	P cur,prev;
	int cost;
	NODE(P C,P p,int c){cur = C, prev = p,cost = c;}
	NODE(){}
};
bool operator<(const NODE &a,const NODE &b){
	return a.cost > b.cost;
}
int w,h,d;
int correct(int x,int y){
	return x >= 0 && y >= 0 && y < h && x < w;
}
int main(){
	while(cin >> h >> w , h && w){
		cin >> d;
		int data[101][20][20];
		
		rep(i,101)rep(j,20)rep(k,20)data[i][j][k] = -1;

		vector< pair<P,P> > stop;
		int add[20][20][20][20] = {0};
		int ns; cin >> ns;
		rep(i,ns){
			int c;
			string t;cin >> t >> c;
			P p = get(t);
			rep(j,101){
				data[j][p.y][p.x] = (j/c)%2; //ayasii
			}
		}
		int nc; cin >> nc;
		rep(i,nc){
			string a,b;cin >> a >> b;
			stop.push_back(make_pair(get(a),get(b)));
			stop.push_back(make_pair(get(b),get(a)));
		}
		sort(stop.begin(),stop.end());
		int nj;cin >> nj;
		rep(i,nj){
			string a,b;int c;cin >> a >> b >> c;
			P A = get(a) , B = get(b);
			add[A.y][A.x][B.y][B.x] = add[B.y][B.x][A.y][A.x] = c;
		}
		bool memo[101][20][20] = {0};
		string S,G; cin >> S >> G;
		P start = get(S) , goal = get(G);
		priority_queue<NODE> Q;
		Q.push(NODE(start,P(start.x-1,start.y),0));
		while(Q.size()){
			NODE q = Q.top(); Q.pop();
			//usleep(30000);
			if(memo[q.cost][q.cur.y][q.cur.x])continue;
			else memo[q.cost][q.cur.y][q.cur.x] = true;
			
			if(q.cur.x == goal.x && q.cur.y == goal.y){
				cout << q.cost << endl;
				break;
			}
			rep(i,4){
				int dir = i/2;
				P nextP = P(q.cur.x+dx[i],q.cur.y+dy[i]);
				int nextCost = q.cost + add[q.cur.y][q.cur.x][nextP.y][nextP.x] + d;
				if(
					nextCost > 100 || 
					!correct(nextP.x,nextP.y) || 
					binary_search(stop.begin(),stop.end(),make_pair(q.cur,nextP)) || 
					(nextP.x == q.prev.x && nextP.y == q.prev.y) || 
					(data[nextCost][nextP.y][nextP.x] != -1 && data[nextCost][nextP.y][nextP.x] == dir)
				){
					continue;
				}
				Q.push( NODE(nextP,q.cur,nextCost) );
			}
		}
	}
}