// -*- coding:utf-8; tab-width:4 -*-
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
#include <limits>
#include <complex>
#include <functional>
#include <iterator>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>

// 解答
namespace solution {
    using namespace std;

    typedef istringstream ISS;
    typedef ostringstream OSS;
    typedef vector<string> VS;
    typedef long long LL;
    typedef int INT;
    typedef vector<INT> VI;
    typedef vector<VI> VVI;
    typedef pair<INT, INT> II;
    typedef map<string, int> TABLE;

    // @snippet<sh19910711/contest:io/config.cpp>
    namespace io {
        const std::string OUTPUT_VECTOR_DELIMITER = ",";
    }

    // @snippet<sh19910711/contest:io/vector.cpp>
    namespace io {
        template <typename T> std::ostream& operator <<( std::ostream& os, std::vector<T>& v ) {
            typedef typename std::vector<T>::iterator Iterator;
            for ( Iterator it_i = v.begin(); it_i != v.end(); ++ it_i ) {
                os << *it_i;
                if ( it_i + 1 != v.end() )
                    os << OUTPUT_VECTOR_DELIMITER;
            }
            return os;
        }
        template <typename T> std::istream& operator >>( std::istream& is, std::vector<T>& v ) {
            int n = v.size();
            for ( int i = 0; i < n; ++ i ) {
                is >> v[i];
            }
            return is;
        }
    }

    using namespace io;

    const int C_SIZE = 8;
    const int EDGES = 301;
    const int INF = INT_MAX / 3;

    int m;
    int n;
    int k;
    int d;
    int C[C_SIZE];
    string A[EDGES];
    string B[EDGES];
    int L[EDGES];

    map<string, int> T;
    int TC;

    class Edge {
    public:
        int a;
        int b;
        int weight;
        Edge( int a, int b, int weight ): a(a), b(b), weight(weight) {}
        friend ostream& operator << ( ostream& os, Edge& e ) {
            os << "{a = " << e.a << ", b = " << e.b << ", " << e.weight << "}";
            return os;
        }
    };
    typedef vector<Edge> Edges;

    class Graph {
    public:
        typedef vector<int> VI;
        typedef vector<VI> VVI;
        VVI G;
        VVI W;
        int n;
        Graph() {}
        Graph( int n, Edges edges ): n(n) {
            G = vector<vector<int> >(n);
            W = vector<vector<int> >( n, vector<int>( n ) );
            for ( Edges::iterator it_i = edges.begin(); it_i != edges.end(); ++ it_i ) {
                addEdge(*it_i);
            }
        }
        void addEdge( Edge e ) {
            G[e.a].push_back(e.b);
            G[e.b].push_back(e.a);
            W[e.a][e.b] = W[e.b][e.a] = e.weight;
        }
        int getCost( int u, int v ) {
            return W[u][v];
        }
        VI::iterator begin( int u ) {
            return G[u].begin();
        }
        VI::iterator end( int u ) {
            return G[u].end();
        }
    };

    class Node {
    public:
        int id;
        int state;
        Node( int id, int state ): id(id), state(state) {}
    };

    class BellmanFord {
    public:
        typedef vector<int> VI;
        typedef vector<VI> VVI;
        Graph* G;
        VVI dist;
        VVI visited;
        VVI next_visited;
        int n;
        int m;
        bool updated;
        BellmanFord( Graph* G_, int n_, int m_ ) {
            G = G_;
            n = n_;
            m = m_;
            dist = VVI( n, VI( 1<<m, INF ) );
            visited = VVI( n, VI( 1<<m, false ) );
        }
        void build( int start ) {
            Node start_node( start, 0 );
            dist[start][0] = 0;
            visited[start][0] = true;

            while ( true ) {
                updated = false;
                next_visited = VVI( n, VI( (1<<m), false ) );
                for ( int i = 0; i < n; ++ i ) {
                    for ( int j = 0; j < ( 1 << m ); ++ j ) {
                        Node node( i, j );
                        if ( ! visited[i][j] )
                            continue;
                        for ( VI::iterator it_i = G->begin(i); it_i != G->end(i); ++ it_i ) {
                            update( node, *it_i );
                        }
                    }
                }
                if ( ! updated )
                    break;
                visited = next_visited;
            }
        }
        void update( Node& node, int to ) {
            if ( m <= to ) {
                int new_dist = dist[node.id][node.state] + G->getCost( node.id, to );
                if ( new_dist < dist[to][node.state] ) {
                    dist[to][node.state] = new_dist;
                    updated = true;
                    next_visited[to][node.state] = true;
                }
            } else {
                int bv = 1 << to;
                if ( node.state & bv )
                    return;
                int new_dist = dist[node.id][node.state] + G->getCost( node.id, to ) - C[to];
                int next_state = node.state | bv;
                if ( new_dist < dist[to][next_state] ) {
                    dist[to][next_state] = new_dist;
                    updated = true;
                    next_visited[to][next_state] = true;
                }
            }

        }
    };

    Graph G;

    struct Solution {
        void init() {
            T.clear();
            TC = 0;
        }

        bool input() {
            cin >> m >> n >> k >> d;
            if ( m == 0 && n == 0 && k == 0 && d == 0 )
                return false;
            for ( int i = 0; i < m; ++ i ) {
                cin >> C[i];
            }
            for ( int i = 0; i < d; ++ i ) {
                cin >> A[i] >> B[i] >> L[i];
            }
            return true;
        }

        string to_string( int n ) {
            OSS oss;
            oss << n;
            return oss.str();
        }

        void add_index( string s ) {
            if ( T.count(s) )
                return;
            T[s] = TC ++;
        }

        int find_index( string s ) {
            return T[s];
        }

        Edges get_edges() {
            Edges res;
            for ( int i = 0; i < d; ++ i ) {
                res.push_back(Edge( find_index(A[i]), find_index(B[i]), L[i] * k ));
            }
            return res;
        }

        int solve() {
            for ( int i = 0; i < m; ++ i )
                add_index("C"+to_string(i+1));
            for ( int i = 0; i < n; ++ i )
                add_index("L"+to_string(i+1));
            add_index("H");
            add_index("D");
            int n = TC;

            Edges edges = get_edges();
            G = Graph(n, edges);
            int start = find_index("H");
            int goal = find_index("D");
            BellmanFord bf( &G, n, m );
            bf.build( start );

            int res = INT_MAX; 
            for ( int i = 0; i < ( 1 << m ); ++ i ) {
                res = min( res, bf.dist[goal][i] );
            }
            return res;
        }

        int run() {
            while ( init(), input() ) {
                cout << solve() << endl;
            }
            return 0;
        }
    };
}

int main() {
    return solution::Solution().run();
}

Measured memory_bytes: 1496