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: Accepted)

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<sstream>
#include<bitset>
using namespace std;
#define INF (1<<29)
#define F first
#define S second
typedef pair<int,int> P;
typedef pair<int,P> PP;
struct edge{
  int t,c;
  edge(int t,int c) : t(t),c(c) {}
};
vector<edge> G[500];
int m,n,k,d;
int H[8];
int getid(string s){
  int id;
  if(s[0]=='H'){
    id = 0;
  } else if(s[0]=='C'){
    stringstream ss;
    ss << s.substr(1);
    ss >> id;
  } else if(s[0]=='L'){
    stringstream ss;
    ss << s.substr(1);
    ss >> id;
    id+=6;
  } else {
    id = 300;
  }
  return id;
}
int h[500][1<<6];
int solve(){
  priority_queue<PP,vector<PP>,greater<PP> > q;
  for(int i=0;i<500;i++)
    for(int j=0;j<(1<<6);j++)
      h[i][j]=INF;
  h[0][0]=0;
  q.push(PP(0,P(0,0)));
  while(!q.empty()){
    PP p = q.top(); q.pop();
    int id = p.S.F;
    int st = p.S.S;
    int c = p.F;
    //cout << id <<" "<< bitset<10>(st)<<" " << c << "\n";
    //sleep(1);
    for(int i=0;i<(int)G[id].size();i++){
      //  cout << G[id][i].t <<" "<< G[id][i].c*k << "\n";
      if( 1<=G[id][i].t && G[id][i].t<=6 ){
	int nst = (1<<(G[id][i].t-1)) | st;
	if( (1<<(G[id][i].t-1)) & st ) continue;
	if( G[id][i].c*k + c + H[G[id][i].t] < h[G[id][i].t][nst] ){
	  h[G[id][i].t][nst] = G[id][i].c*k + c + H[G[id][i].t]; 
	  q.push( PP(G[id][i].c*k + c + H[G[id][i].t],
		     P(G[id][i].t,nst) ) );
	}
      } else {
	if( G[id][i].c*k + c < h[G[id][i].t][st] ){
	  h[G[id][i].t][st] = G[id][i].c*k + c;
	  q.push( PP(G[id][i].c*k + c,
		     P(G[id][i].t, st) ) );
	}
      }
    }
  }
  int ret = INF;
  for(int i=0;i<(1<<6);i++)
    ret = min(ret,h[300][i]);
  return ret;
}
int main(){
  while(1){
    cin >> m >> n >> k >> d;
    if(!m && !n && !k && !d) break;
    for(int i=0;i<500;i++) G[i].clear();
    for(int i=1;i<=m;i++){
      cin >> H[i];
      H[i]*=-1;
    }
    for(int i=0;i<d;i++){
      string a,b;
      int c;
      cin >> a >> b >> c;
      int ida = getid(a);
      int idb = getid(b);
      //cout << ida << " " << idb <<" "<< endl;
      G[ida].push_back( edge(idb,c) );
      G[idb].push_back( edge(ida,c) );
    }
    cout << solve() << "\n";
  }
}