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: Time Limit Exceeded)

#include<stdio.h>
#include<string.h>
#include<stdbool.h>

#define MIN(x,y) (((x)<(y))?(x):(y))
#define INFTY (1<<21)


int m, n, k, d, C[7], G[110][110], N, D[110][64];

int getID(char *str);
int isC(int x);
int bellman(void);

int main(void){
  char source[16], target[16];
  int cost,s,t;
  int i,j;
  while(scanf("%d%d%d%d%*c",&m,&n,&k,&d) && m ){
    N = 2 + n + m;
    for(i=1;i<m+1;i++) scanf("%d%*c",&C[i]);
    for(i=0;i<N;i++) for(j=0;j<N;j++) G[i][j] = INFTY;
    for(i=0;i<d;i++){
      scanf("%s%*c%s%*c%d%*c",source,target,&cost);
      s = getID(source);
      t = getID(target);
      G[t][s] = G[s][t] = MIN(G[s][t], cost * k);
    }
    printf("%d\n",bellman());
  }
  return 0;
}

int getID(char *str){
  char num[16];
  if ( str[0] == 'H' ) return 0;
  if ( str[0] == 'D' ) return N - 1;
  strcpy(num,str+1);
  if ( str[0] == 'C' ) return atoi(num);
  return atoi(num) + m;
}

int isC(int x){
  return 1 <= x && x <= m;
}
int bellman(void){
  bool change=0;
  int minv;
  int i,o,u,v,b,j;

  for(i=0;i<N;i++) for(j=0;j<(1<<m);j++) D[i][j] = INFTY;
  D[0][0] = 0;
  for(o=0;o<N*(1<<m);o++){
    for(u=0;u<N;u++){
      for(v=0;v<N;v++){
	if ( u == v || G[u][v] == INFTY ) continue;
	for(b=0;b<(1<<m);b++){
	  if (isC(v) && (b&(1<<(v-1))) != 0 ) continue;
	  if ( isC(v) ) {
	    if ( D[u][b] + G[u][v] - C[v] < D[v][b|(1<<(v-1))] ) {
	      D[v][b|(1<<(v-1))] = D[u][b] + G[u][v] - C[v];
	      change = true;
	    }
	  } else {
	    if ( D[u][b] + G[u][v] < D[v][b] ){
	      D[v][b] = D[u][b] + G[u][v];
	      change = true;
	    }
	  }
	}
      }
    }
    if ( !change ) break;
  }
  minv = INFTY;
  for(i=0;i<(1<<m);i++) minv = MIN(minv, D[N-1][i]);
  return minv;
}