Problem:
自転車でダイエット

A さんは甘いものが大好きですが、最近は奥さんからダイエットするように言われています。ある日、A さんが自宅から市役所に出かけるとき、奥さんは自転車で行くことを勧めました。そこでA さんはしぶしぶ自転車に乗って出かけましたが、甘い物の好きな A さんは、途中にあるケーキ屋さんに立ち寄りケーキの食べ歩きをしようと思いつきました。

自転車をこげば走行距離に応じてカロリーが消費されますが、ケーキを食べればその分カロリーが摂取されます。正味の消費カロリーは、自転車をこいで消費したカロリーからケーキを食べて摂取したカロリーを引いた値になります。したがって、正味の消費カロリーが 0 より小さくなることもあります。

ケーキ屋さんでケーキを買ったら、 Aさんはその場でケーキを全部食べてしまいます。 Aさんがすべてのケーキ屋さんに立ち寄るとは限りませんが、ケーキ屋さんが存在する地点を通るときには、必ず立ち寄ってケーキを 1 つ買って食べるものとします。ただし、同じケーキ屋さんの前を何度も通るのはさすがに気がひけるので、各ケーキ屋さんに訪れられるのは 1 回だけとします。また、目的地の市役所をいったん通り過ぎてからケーキ屋さんに立ち寄り、その後で市役所に戻って用を済ませてもよいものとし、ケーキ屋さん以外は何度訪れても良いものとします。

A さんの自宅から市役所までの地図情報と、その途中にあるケーキ屋さんで食べられるケーキのカロリーの一覧、単位距離の走行による消費カロリーを入力とし、自宅を出発してから市役所に入るまでの正味の消費カロリーの最小値を出力するプログラムを作成してください。

地図には、A さんの自宅と市役所、ケーキ屋さんとランドマーク(目印)になる建物が書かれています。地図を表す入力データは、A さんの自宅、市役所、ケーキ屋さんとランドマークの各地点の間をつなぐ道があるとき、2 つの地点を表す記号とその間の距離からなる行を含みます。たとえば、5 番目のケーキ屋さんと 3 番目のランドマークの間の距離が 10 なら、入力データは以下のような行を含みます。

C5 L3 10

このようにケーキ屋さんには C、ランドマークには L を番号の前につけて表します。また、A さんの自宅は H、市役所は D で表します。入力データに 2 つの地点とその間の距離が与えられているなら、2 地点の間をどちら向きにも進めます。たとえば、上の例ではケーキ屋さんからランドマークへも、その逆向きへも進むことができます。また、自宅から市役所までは必ずたどり着けるものとします。それ以外に与えられる入力データは、ケーキ屋さんの数 m、ランドマークの数 n、単位距離あたりの消費カロリー k、 1 番目のケーキ屋さんから m 番目のケーキ屋さんまでのそれぞれで買えるケーキのカロリーを表す m 個のデータ、距離のデータの総数 d です。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりは四つの 0 の行で示されます。
各データセットは以下の形式で与えられます。

m n k d
c1 c2 ... cm
s1 t1 e1
s2 t2 e2
:
sd td ed

1 行目にケーキ屋さんの数 m (1 ≤ m ≤ 6)、 ランドマークの数 n (1 ≤ n ≤ 100) 、単位距離あたりの消費カロリー k (1 ≤ k ≤ 5)、距離のデータの総数 d (5 ≤ d ≤ 256) が与えられます。

2 行目に各ケーキ屋で買うケーキのカロリー ci (1 ≤ ci ≤ 100) が与えられます。

続く d 行に i 番目の 2 つの地点間の距離データ si, ti, ei (1 ≤ ei ≤ 20) が与えられます。

データセットの数は 100 を超えません。

Output

入力データセットごとに、全体の消費カロリーの最小値を１行に出力します。

Sample Input

1 1 2 5
35
H L1 5
C1 D 6
C1 H 12
L1 D 10
C1 L1 20
2 1 4 6
100 70
H L1 5
C1 L1 12
C1 D 11
C2 L1 7
C2 D 15
L1 D 8
0 0 0 0

Output for the Sample Input

1
-2

Solution in C++ (judge verdict: Wrong Answer)

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>

using namespace std;

#define NODE (128)
#define INF (100000000)
#define SHOP (8)

int cost[NODE][NODE];
int v[1 << (SHOP)][NODE];
bool done[1 << (SHOP)][NODE];
int V;
int m, n, k, d;
int cake[SHOP];

typedef struct{
    int pos;
    int val;
    int bit;
} State;

bool operator > (const State &a, const State &b)
{
    return (a.val > b.val);
}

void dijkstra()
{
    priority_queue<State, vector<State>, greater<State> > que;
    State st;
    
    st.pos = 0, st.val = 0, st.bit = 0;
    que.push(st);
    
    done[0][0] = 1;
    
    for (int i = 0; i < 1 << (SHOP); i++){
        for (int j = 0; j < V; j++){
            v[i][j] = INF;
        }
    }
    v[0][0] = 0;
    
    memset(done, false, sizeof(done));
    
    while (!que.empty()){
        State temp = que.top(); que.pop();
        for (int i = 0; i < V; i++){
            if (i == temp.pos || cost[temp.pos][i] == INF){
                continue;
            }
            
            State next;
            next.val = temp.val + cost[temp.pos][i];
            next.pos = i;
            next.bit = temp.bit;
            if (1 <= i && i <= m){
                if (((temp.bit >> (i - 1)) & 1) == 0){
                    next.bit = temp.bit | (1 << (i - 1));
                    next.val -= cake[i - 1];
                }
            }
            
            if (!done[next.bit][i]){
                done[next.bit][i] = true;
                v[next.bit][i] = next.val;
                que.push(next);
            }
        }
    }
}

int main(void)
{
	int i, j, l;
	int from, to;
    int cal;
    char div[5];
	
	while (1){
		scanf("%d%d%d%d", &m, &n, &k, &d);
        if (m + n + k + d == 0){
            break;
        }
		
        V = m + n + 2;
        
        for (i = 0; i < m; i++){
            scanf("%d", &cake[i]);
        }
		
		for (i = 0; i < V; i++){
			for (j = 0; j < V; j++){
				cost[i][j] = INF;
			}
            cost[i][i] = 0;
		}
		
        for (i = 0; i < d; i++){
			scanf("%s", div);
            switch(div[0]){
                case 'H':
                from = 0;
                break;
                
                case 'D':
                from = m + n + 1;
                break;
                
                case 'C':
                from = atoi(&div[1]);
                break;
                
                case 'L':
                from = atoi(&div[1]) + m;
                break;
            }
            
            scanf("%s", div);
            switch(div[0]){
                case 'H':
                to = 0;
                break;
                
                case 'D':
                to = m + n + 1;
                break;
                
                case 'C':
                to = atoi(&div[1]);
                break;
                
                case 'L':
                to = atoi(&div[1]) + m;
                break;
            }
            
            scanf("%d", &cal);
            
			cost[from][to] = cost[to][from] = cal * k;
		}
		
        int ans = INF;
        
        dijkstra();
        
        for (i = 0; i < 1 << (SHOP); i++){
            ans = min(ans, v[i][m + n + 1]);
        }
        
		printf("%d\n", ans);
	}
	return (0);
}