#include <bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
const int INF = 1000000001;
const long long int LLINF = 1000000000000000001LL;
struct base {
  double x, y;
  base() { x = 0, y = 1; }
  base(double a) : x(a), y(0) {}
  base(double x, double y) : x(x), y(y) {}
  double real() { return x; }
};
inline base operator+(const base& a, const base& b) {
  return base(a.x + b.x, a.y + b.y);
}
inline base operator-(const base& a, const base& b) {
  return base(a.x - b.x, a.y - b.y);
}
inline base operator*(const base& a, const base& b) {
  return base(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
}
inline base operator/(const base& a, const double& b) {
  return base(a.x / b, a.y / b);
}
inline base operator/(const base& a, const base& b) {
  return base(a.x * b.x + a.y * b.y, a.y * b.x - a.x * b.y) /
         (b.x * b.x + b.y * b.y);
}
const double MPI = acos(-1);
struct FFT {
  vector<base> e[2];
  void fft(vector<base>& x, int d = 1) {
    int n = x.size(), ind = (d + 1) / 2;
    if (e[ind].empty()) {
      e[ind].resize(n);
      for (int i = (0); i <= (n - 1); ++i) {
        e[ind][i] = base(cos(2 * MPI * i / n), -d * sin(2 * MPI * i / n));
      }
    }
    for (int i = (0); i <= (n - 1); ++i) {
      int j = 0;
      for (int k = 1; k < n; k <<= 1, j <<= 1) {
        if (k & i) j++;
      }
      j >>= 1;
      if (i < j) swap(x[i], x[j]);
    }
    int k = 0;
    while ((1 << k) < n) k++;
    for (int s = 1; s < n; s <<= 1) {
      --k;
      for (int i = 0; i < n; i += 2 * s)
        for (int j = (0); j <= (s - 1); ++j) {
          base u = x[i + j], v = x[i + j + s] * e[ind][j << k];
          x[i + j] = u + v;
          x[i + j + s] = u - v;
        }
    }
  }
  void convolution(vector<base>& ca, vector<base>& cb) {
    int n = (int)(cb).size();
    ca.resize(n);
    fft(ca);
    for (int i = (0); i <= (n - 1); ++i) {
      ca[i] = ca[i] * cb[i];
    }
    fft(ca, -1);
  }
};
vector<FFT> fft;
struct OnlineFFT {
  vector<base> a;
  vector<double> res;
  double b0, b1;
  vector<vector<base> > parts;
  OnlineFFT(int k, vector<double>& b) {
    b0 = b[0];
    b1 = b[1];
    b.resize(1 << k, 0);
    res.resize(1 << k, 0);
    parts.resize(k);
    for (int i = (0); i <= (k - 1); ++i) {
      int l = 1 << i, r = 1 << (i + 1);
      parts[i].resize(1 << (i + 1), 0);
      for (int ind = (l); ind <= (r - 1); ++ind) {
        parts[i][ind - l] = b[ind];
      }
      fft[i].fft(parts[i]);
      for (auto& elem : parts[i]) elem = elem / (int)(parts[i]).size();
    }
  }
  double nextElement(int i, double ai) {
    a.push_back(ai);
    res[i] += ai * b0;
    res[i + 1] += ai * b1;
    int exp = 1, pw = 2;
    while (i > 0 && i % pw == 0) {
      vector<base> part(a.begin() + i - pw, a.begin() + i);
      fft[exp].convolution(part, parts[exp]);
      for (int j = (0); j <= ((int)(part).size() - 1); ++j) {
        if (j + i >= (int)(res).size()) break;
        res[j + i] += part[j].real();
      }
      exp++;
      pw *= 2;
    }
    return res[i];
  }
};
struct edge {
  int u, v, cost;
  vector<double> prob, probSuff;
};
const double DINF = 1e12;
int main() {
  int n, m, t, x;
  scanf("%d %d %d %d", &n, &m, &t, &x);
  int k = 1;
  while ((1 << k) <= t) k++;
  fft.resize(k);
  vector<edge> edges(m);
  for (int i = (0); i <= (m - 1); ++i) {
    scanf("%d %d %d", &edges[i].u, &edges[i].v, &edges[i].cost);
    edges[i].u--;
    edges[i].v--;
    const double DIV = 100000.0;
    edges[i].prob.resize(t + 1, 0);
    for (int j = (0); j <= (t - 1); ++j) {
      int p;
      scanf("%d", &p);
      edges[i].prob[j] = (double)p / DIV;
    }
    edges[i].probSuff = edges[i].prob;
    for (int j = (t - 2); j >= (0); --j) {
      edges[i].probSuff[j] += edges[i].probSuff[j + 1];
    }
  }
  vector<int> distToSink(n, INF);
  distToSink[n - 1] = 0;
  for (int _ = (1); _ <= (n); ++_)
    for (int i = (0); i <= (m - 1); ++i) {
      distToSink[edges[i].u] =
          min(distToSink[edges[i].u], edges[i].cost + distToSink[edges[i].v]);
    }
  vector<double> forVertex(n, DINF), forEdge(m, DINF);
  for (int i = (0); i <= (n - 1); ++i) {
    forVertex[i] = distToSink[i] + (i < n - 1 ? x : 0);
  }
  vector<OnlineFFT> forEdgeFFT;
  for (int i = (0); i <= (m - 1); ++i)
    forEdgeFFT.emplace_back(k, edges[i].prob);
  for (int time = (1); time <= (t); ++time) {
    for (int j = (0); j <= (m - 1); ++j) {
      forEdge[j] = 0.0;
      forEdge[j] += edges[j].cost;
      forEdge[j] += forEdgeFFT[j].nextElement(time - 1, forVertex[edges[j].v]);
      forEdge[j] += edges[j].probSuff[time] * (x + distToSink[edges[j].v]);
    }
    for (int j = (0); j <= (n - 1); ++j) {
      forVertex[j] = (j < n - 1 ? DINF : 0);
    }
    for (int j = (0); j <= (m - 1); ++j) {
      int u = edges[j].u;
      forVertex[u] = min(forVertex[u], forEdge[j]);
    }
  }
  printf("%.9lf", forVertex[0]);
  return 0;
}
