/*
#include<iostream>
#define int long long
using namespace std;
int solve() {
int a = 0, b = 0, c = 0;
cin >> a >> b >> c;
int ans = b * c;
int num = 1, time = 0;
bool flag = true;
while (flag) {
time++;
num *= 2;
int res = time * a + ((c + num - 1) / num) * b;
if (res > ans) {
flag = false;
}
else {
ans = res;
}
}
return ans;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 0;
cin >> t;
while (t--) {
int ans = solve();
cout << ans << endl;
}
return 0;
}
*/
/*
#include<iostream>
#include<algorithm>
#include<vector>
#define int long long
using namespace std;
const int N = 1e6 + 9;
int L[N], R[N];
int solve() {
int l = 0, r = 0;
cin >> l >> r;
int Lpos = 0, Rpos = 0;
while (l) {
Lpos++;
L[Lpos] = l % 3;
l /= 3;
}
while (r) {
Rpos++;
R[Rpos] = r % 3;
r /= 3;
}
int res = 0, ans = 0;
bool flag = false;
for (int i = Rpos; i >= 1; i--) {
if (R[i] > L[i]) {
flag = true;
}
if (flag) {
if (R[i] == 2) {
res = max(res, ans + 2 + (i - 1) * 3);
}
else if (R[i] == 1) {
if (i == Rpos) {
res = max(res, ans + (i - 1) * 3);
}
else {
res = max(res, ans + 1 + (i - 1) * 3);
}
}
}
ans += R[i] + 1;
}
while (Lpos) {
L[Lpos] = 0;
Lpos--;
}
return max(ans, res);
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 0;
cin >> t;
while (t--) {
int ans = solve();
cout << ans << endl;
}
return 0;
}
*/
/*
#include<iostream>
#include<string>
#include<map>
#define int long long
using namespace std;
signed main() {
int n = 0, a = 0, b = 0;
cin >> n >> a >> b;
int result = 0;
for (int i = 1; i <= n; i++) {
int ans = 0;
string s;
cin >> s;
map<char, int>mp;
int num = 0;
for (int j = 0; j < 3; j++) {
mp[s[j]]++;
if (mp[s[j]] == 1) {
num++;
}
}
if (num == 3) {
ans = 3 * min(a, b);
}
if (num == 2) {
ans = min(min(3 * a, 3 * b), min(a + b, 2 * b));
}
if (num == 1) {
ans = min(min(3 * a, 3 * b), min(a + b, 2 * b));
}
result += ans;
}
cout << result << endl;
return 0;
}
*/
/*
#include<iostream>
#include<string>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
bool cmp(string a, string b) {
return a.length() < b.length();
}
signed main() {
int n = 0, ans = 0;
cin >> n;
vector<string>s(n);
for (int i = 0; i < n; i++) {
cin >> s[i];
}
sort(s.begin(), s.end(), cmp);
set<string>st;
for (int i = 0; i < n; i++) {
if (s[i].size() == 1 || st.count(s[i].substr(0, s[i].length() - 1)) && st.count(s[i].substr(1))) {
st.insert(s[i]);
ans = max(ans, (int)s[i].length());
}
}
cout << ans << endl;
return 0;
}
*/
/*
#include<iostream>
#include<algorithm>
#include<vector>
#define int long long
using namespace std;
signed main() {
int n = 0;
cin >> n;
vector<int>v(n);
for (int i = 0; i < n; i++) {
cin >> v[i];
}
sort(v.begin(), v.end());
int ans = 0;
for (int i = n - 2; i < n; i++) {
if (i >= 0 && v[i] >= 0) {
ans += v[i];
}
}
cout << ans << endl;
return 0;
}
*/
/*
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 1e6 + 9;
vector<int>edge[N],v;
int len[N], son[N];
bool cmp(int a, int b) {
return a > b;
}
void init(int n) {
v.clear();
for (int i = 0; i <= n; i++) {
edge[i].clear();
len[i] = son[i] = 0;
}
}
void dfs1(int u) {
for (auto v : edge[u]) {
dfs1(v);
if (len[v] > len[son[u]]) {
son[u] = v;
}
}
len[u] = len[son[u]] + 1;
}
void dfs2(int u, int l) {
if (!son[u]) {
v.push_back(l);
return;
}
dfs2(son[u], l + 1);
for (auto v : edge[u]) {
if (v != son[u]) {
dfs2(v, 1);
}
}
}
int solve() {
int n = 0;
cin >> n;
init(n);
for (int i = 2; i <= n; i++) {
int u = 0;
cin >> u;
edge[u].push_back(i);
}
dfs1(1);
dfs2(1, 1);
sort(v.begin(), v.end(), cmp);
int ans = v.size();
for (int i = 0; i < (int)v.size(); i++) {
ans = min(ans, i + v[i]);
}
return ans;
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 0;
cin >> t;
while (t--) {
int ans = solve();
cout << ans << endl;
}
return 0;
}
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
const int N = 509, M = N * N,INF = INT_MAX;
char s[N][N];
int sc[N], cl[N],head[N],dis[N],gap[N],cur[N],q[N];
int total = 1,n,m,S,T,nod;
struct Edge {
int next, to, flow;
}edge[M << 1];
void addedge(int u, int v, int val) {
total++;
edge[total].to = v;
edge[total].flow = val;
edge[total].next = head[u];
head[u] = total;
}
void AddEdge(int u, int v, int w) {
addedge(u, v, w);
addedge(v, u, 0);
}
void bfs() {
int Head = 0, Tail = 0;
Tail++;
q[Tail] = T;
gap[dis[T]]++;
dis[T] = 1;
while (Head < Tail) {
Head++;
int x = q[Head];
for (int i = head[x]; i; i = edge[i].next) {
int y = edge[i].to;
if ((!dis[y]) && edge[i ^ 1].flow) {
dis[y] = dis[x] + 1;
gap[dis[y]]++;
Tail++;
q[Tail] = y;
}
}
}
}
int dfs(int x, int a) {
if (x == T || (!a)) {
return a;
}
int flow = 0, f;
for (int& i = cur[x]; i; i = edge[i].next) {
if (dis[x] == dis[edge[i].to] + 1) {
f = dfs(edge[i].to, min(a, edge[i].flow));
edge[i].flow -= f;
edge[i ^ 1].flow += f;
a -= f;
flow += f;
if (!a) {
return flow;
}
}
}
gap[dis[x]]--;
if (!gap[dis[x]]) {
dis[S] = nod + 1;
}
dis[x]++;
gap[dis[x]]++;
return flow;
}
int ISAP() {
static int ans = 0;
bfs();
while (dis[S] <= nod) {
memcpy(cur + 1, head + 1, sizeof(*head) * nod);
ans += dfs(S, INF);
}
return ans;
}
void solve() {
int c = 0, d = 0, K = 0, sum = 0;
cin >> n >> m >> c >> d;
for (int i = 1; i <= n; i++) {
cin >> (s[i] + 1);
for (int j = 1; j <= m; j++) {
if (s[i][j] == '.') {
s[i][j] = 1;
}
else {
s[i][j] = 0;
}
sc[i] += s[i][j];
cl[j] += s[i][j];
K = max(K, cl[j]);
}
K = max(K, sc[i]);
sum += sc[i];
}
S = n + m + 1;
T = nod = S + 1;
for (int i = 1; i <= n; i++) {
AddEdge(S, i, 0);
}
for (int i = 1; i <= m; i++) {
AddEdge(i + n, T, 0);
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (s[i][j]) {
AddEdge(i, j + n, 1);
}
}
}
int ans = LLONG_MAX;
for (int k = 0; k <= K; k++) {
if (k) {
memset(gap + 1, 0, sizeof(*gap) * nod);
memset(dis + 1, 0, sizeof(*dis) * nod);
for (int i = 1; i <= n; i++) {
edge[i * 2].flow++;
}
for (int i = 1; i <= m; i++) {
edge[(i + n) * 2].flow++;
}
}
ans = min(ans, c * k + d * (sum - ISAP()));
}
cout << ans << endl;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
solve();
return 0;
}