import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.util.Comparator;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.io.IOException;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.math.BigInteger;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Egor Kulikov (egor@egork.net)
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		OutputWriter out = new OutputWriter(outputStream);
		TaskC solver = new TaskC();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskC {
	int RIGHT = 3;
	int LEFT = 1;

    public void solve(int testNumber, InputReader in, OutputWriter out) {
		int rowCount = in.readInt();
		int columnCount = in.readInt();
		char[][] table = IOUtils.readTable(in, rowCount, columnCount);
		int treasureCount = 0;
		int bombCount = 0;
		int sRow = -1;
		int sColumn = -1;
		for (int i = 0; i < rowCount; i++) {
			for (int j = 0; j < columnCount; j++) {
				char c = table[i][j];
				if (Character.isDigit(c))
					treasureCount = Math.max(treasureCount, c - '0');
				else if (c == 'B')
					bombCount++;
				else if (c == 'S') {
					sRow = i;
					sColumn = j;
				}
			}
		}
		table[sRow][sColumn] = '.';
		int[] value = IOUtils.readIntArray(in, treasureCount);
		int[][][] change = new int[4][rowCount][columnCount];
		int bombIndex = treasureCount;
		for (int i = 0; i < rowCount; i++) {
			for (int j = 0; j < columnCount; j++) {
				int curIndex = -1;
				if (Character.isDigit(table[i][j]))
					curIndex = table[i][j] - '1';
				else if (table[i][j] == 'B')
					curIndex = bombIndex++;
				if (curIndex == -1)
					continue;
				for (int k = 0; k < i; k++) {
					change[RIGHT][k][j] += 1 << curIndex;
					if (j + 1 < columnCount)
						change[LEFT][k][j + 1] += 1 << curIndex;
				}
			}
		}
		int count = treasureCount + bombCount;
		int[][][] cost = new int[rowCount][columnCount][1 << count];
		ArrayUtils.fill(cost, -1);
		cost[sRow][sColumn][0] = 0;
		int[] rowQueue = new int[rowCount * columnCount * (1 << count)];
		int[] columnQueue = new int[rowQueue.length];
		int[] maskQueue = new int[rowQueue.length];
		rowQueue[0] = sRow;
		columnQueue[0] = sColumn;
		int length = 1;
		for (int i = 0; i < length; i++) {
			int row = rowQueue[i];
			int column = columnQueue[i];
			int mask = maskQueue[i];
			for (int j = 0; j < 4; j++) {
				int nRow = row + MiscUtils.DX4[j];
				int nColumn = column + MiscUtils.DY4[j];
				int nMask = mask ^ change[j][row][column];
				if (!MiscUtils.isValidCell(nRow, nColumn, rowCount, columnCount) || table[nRow][nColumn] != '.' ||
					cost[nRow][nColumn][nMask] != -1)
				{
					continue;
				}
				cost[nRow][nColumn][nMask] = cost[row][column][mask] + 1;
				rowQueue[length] = nRow;
				columnQueue[length] = nColumn;
				maskQueue[length++] = nMask;
			}
		}
		int answer = 0;
		for (int i = 0; i < (1 << treasureCount); i++) {
			if (cost[sRow][sColumn][i] != -1) {
				int candidate = -cost[sRow][sColumn][i];
				for (int j = 0; j < treasureCount; j++) {
					if ((i >> j & 1) == 1)
						candidate += value[j];
				}
				answer = Math.max(answer, candidate);
			}
		}
		out.printLine(answer);
    }
}

class InputReader {

	private InputStream stream;
	private byte[] buf = new byte[1024];
	private int curChar;
	private int numChars;
	private SpaceCharFilter filter;

	public InputReader(InputStream stream) {
		this.stream = stream;
	}

	public int read() {
		if (numChars == -1)
			throw new InputMismatchException();
		if (curChar >= numChars) {
			curChar = 0;
			try {
				numChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (numChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int readInt() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public boolean isSpaceChar(int c) {
		if (filter != null)
			return filter.isSpaceChar(c);
		return isWhitespace(c);
	}

	public static boolean isWhitespace(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	public char readCharacter() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		return (char) c;
	}

	public interface SpaceCharFilter {
		public boolean isSpaceChar(int ch);
	}
}

class OutputWriter {
	private final PrintWriter writer;

	public OutputWriter(OutputStream outputStream) {
		writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
	}

	public OutputWriter(Writer writer) {
		this.writer = new PrintWriter(writer);
	}

	public void close() {
		writer.close();
	}

	public void printLine(int i) {
		writer.println(i);
	}
}

class IOUtils {

	public static int[] readIntArray(InputReader in, int size) {
		int[] array = new int[size];
		for (int i = 0; i < size; i++)
			array[i] = in.readInt();
		return array;
	}

	public static char[] readCharArray(InputReader in, int size) {
		char[] array = new char[size];
		for (int i = 0; i < size; i++)
			array[i] = in.readCharacter();
		return array;
	}

	public static char[][] readTable(InputReader in, int rowCount, int columnCount) {
		char[][] table = new char[rowCount][];
		for (int i = 0; i < rowCount; i++)
			table[i] = readCharArray(in, columnCount);
		return table;
	}

	}

class ArrayUtils {

	public static void fill(int[][] array, int value) {
		for (int[] row : array)
			Arrays.fill(row, value);
	}

	public static void fill(int[][][] array, int value) {
		for (int[][] subArray : array)
			fill(subArray, value);
	}

	}

class MiscUtils {
	public static final int[] DX4 = {1, 0, -1, 0};
	public static final int[] DY4 = {0, -1, 0, 1};

    public static boolean isValidCell(int row, int column, int rowCount, int columnCount) {
		return row >= 0 && row < rowCount && column >= 0 && column < columnCount;
	}

	}


import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Div1C {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt(), m = in.nextInt();
		char[][] g = new char[n][];
		for (int i = 0; i < n; i++)
			g[i] = in.next().toCharArray();
		Point start = null;
		int t = 0, b = 0;
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++) {
				if (Character.isDigit(g[i][j])) {
					t = Math.max(t, (int) (g[i][j] - '0'));
				} else if (g[i][j] == 'B') {
					b++;
				} else if (g[i][j] == 'S') {
					start = new Point(i, j);
				}
			}
		Point[] treasure = new Point[t];
		int[] value = new int[t];
		Point[] boom = new Point[b];
		for (int i = 0, bi = 0; i < n; i++)
			for (int j = 0; j < m; j++) {
				if (Character.isDigit(g[i][j])) {
					int ti = g[i][j] - '1';
					treasure[ti] = new Point(i, j);
				} else if (g[i][j] == 'B') {
					boom[bi++] = new Point(i, j);
				}
			}
		for (int ti = 0; ti < t; ti++)
			value[ti] = in.nextInt();
		int[][][][] cost = new int[n][m][1 << t][1 << b];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				for (int k = 0; k < (1 << t); k++) {
					for (int l = 0; l < (1 << b); l++) {
						cost[i][j][k][l] = 19930309;
					}
				}
			}
		}
		Queue<State> queue = new LinkedList<State>();
		State state = new State(start, 0, 0);
		cost[state.p.x][state.p.y][state.ts][state.bs] = 0;
		queue.add(state);
		while (!queue.isEmpty()) {
			state = queue.remove();
			final int[] dx = new int[] { 0, 0, 1, -1 };
			final int[] dy = new int[] { -1, 1, 0, 0 };
			for (int d = 0; d < 4; d++) {
				State nstate = new State(new Point(state.p.x + dx[d], state.p.y
						+ dy[d]), state.ts, state.bs);
				if (nstate.p.x >= 0 && nstate.p.x < n && nstate.p.y >= 0
						&& nstate.p.y < m
						&& !Character.isDigit(g[nstate.p.x][nstate.p.y])
						&& g[nstate.p.x][nstate.p.y] != '#'
						&& g[nstate.p.x][nstate.p.y] != 'B') {
					for (int i = 0; i < t; i++) {
						if (cross(treasure[i], state.p, nstate.p)) {
							nstate.ts ^= 1 << i;
						}
					}
					for (int i = 0; i < b; i++) {
						if (cross(boom[i], state.p, nstate.p)) {
							nstate.bs ^= 1 << i;
						}
					}
					if (cost[nstate.p.x][nstate.p.y][nstate.ts][nstate.bs] > cost[state.p.x][state.p.y][state.ts][state.bs] + 1) {
						cost[nstate.p.x][nstate.p.y][nstate.ts][nstate.bs] = cost[state.p.x][state.p.y][state.ts][state.bs] + 1;
						queue.add(nstate);
					}
				}
			}
		}
		int answer = 0;
		for (int ts = 0; ts < (1 << t); ts++) {
			int get = 0;
			for (int i = 0; i < t; i++)
				if ((ts & (1 << i)) != 0) {
					get += value[i];
				}
			get -= cost[start.x][start.y][ts][0];
			answer = Math.max(answer, get);
		}
		System.out.println(answer);
	}

	private static boolean cross(Point p, Point l1, Point l2) {
		return (l1.y > p.y) != (l2.y > p.y)
				&& p.x * (l2.y - l1.y) * (l2.y - l1.y) < (l2.x - l1.x)
						* (p.y - l1.y) * (l2.y - l1.y) + l1.x * (l2.y - l1.y)
						* (l2.y - l1.y);
	}
}

class Point {
	public int x, y;

	public Point(int x, int y) {
		this.x = x;
		this.y = y;
	}
}

class State {
	Point p;
	public int ts, bs;

	public State(Point p, int ts, int bs) {
		this.p = p;
		this.ts = ts;
		this.bs = bs;
	}
}


import java.util.*;
import java.io.*;

public class Main {

	BufferedReader in;
	StringTokenizer str = null;
	PrintWriter out;

	private String next() throws Exception{
		if (str == null || !str.hasMoreElements())
			str = new StringTokenizer(in.readLine());
		return str.nextToken();
	}

	private int nextInt() throws Exception{
		return Integer.parseInt(next());
	}

	private long nextLong() throws Exception{
		return Long.parseLong(next());
	}

	private double nextDouble() throws Exception{
		return Double.parseDouble(next());
	}

	int dx[] = new int[]{1, 0, -1, 0};
	int dy[] = new int[]{0, -1, 0, 1};

	int n,m;
	char maze[][];
	int state[][];

	boolean used[][][];
	int d[][][];

	public void run() throws Exception{
		in =  new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);

		n = nextInt();
		m = nextInt();

		int sx = -1;
		int sy = -1;

		state = new int[n][m];

		int treasure = 0;
		maze = new char[n][m];
		for(int i=0;i<n;i++){
			maze[i] = next().toCharArray();
			for(int j=0;j<m;j++){
				if (maze[i][j] == 'S') {
					sx = i;
					sy = j;
					maze[i][j] = '.';
				}else if ('0' <= maze[i][j] && maze[i][j] <= '9') {
					int idx = maze[i][j] - '1';
					for(int k=j+1;k<m;k++){
						state[i][k]|=1<<idx;
					}
					treasure++;
				}
			}
		}

		int []a = new int[treasure];
		for(int i=0;i<treasure;i++) a[i] = nextInt();

		int sum[] = new int[1<<10];
		for(int i=0;i<1<<treasure;i++) {
			for(int j=0;j<treasure;j++) {
				if ((i & (1<<j)) > 0) {
					sum[i]+=a[j];
				}
			}
		}

		int bomb = treasure;
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				if (maze[i][j] == 'B') {
					for(int k=j+1;k<m;k++){
						state[i][k]|=1<<bomb;
					}
					bomb++;
				}
			}
		}

		used = new boolean[n][m][1<<bomb];
		d = new int[n][m][1<<bomb];

		bfs(sx, sy);
		int ans = 0;
		for(int i=0;i<1<<treasure;i++){
			if (used[sx][sy][i]) {
				ans = Math.max(ans, sum[i] - d[sx][sy][i]);
			}
		}

		out.println(ans);
		out.close();
	}

	Queue<int[]> q;

	private void bfs(int sx, int sy) {
		q = new LinkedList<int[]>();
		q.add(new int[]{sx, sy, 0});
		used[sx][sy][0] = true;
		d[sx][sy][0] = 0;

		while(q.size() > 0){
			int cur[] = q.poll();
			int x = cur[0], y = cur[1], nst = cur[2];

			for(int i=0;i<4;i++){
				int nx = x + dx[i], ny = y + dy[i], nstate = nst;
				if (!can(nx, ny)) continue;
				if (dx[i] == 1) {
					nstate^=state[nx][ny];
				}else if (dx[i] == -1) {
					nstate^=state[x][y];
				}

				if (used[nx][ny][nstate]) continue;
				used[nx][ny][nstate] = true;
				d[nx][ny][nstate] = d[x][y][nst] + 1;
				q.add(new int[]{nx, ny, nstate});
			}
		}
	}

	private boolean can(int x, int y) {
		if (x < 0 || y < 0) return false;
		if (x >=n || y >= m) return false;
		if (maze[x][y] != '.') return false;
		return true;
	}

	public static void main(String[] args) throws Exception{
		new Main().run();
	}
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

import static java.lang.Double.parseDouble;
import static java.lang.Integer.MAX_VALUE;
import static java.lang.Integer.bitCount;
import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;

public class Main {
    public static void main(String[] args) throws IOException {
        Solver sv = new Solver();
        sv.solve();
    }
}

class Solver {
    BufferedReader in;
    StringTokenizer tok;

    public void solve() throws IOException {
        in = new BufferedReader(new InputStreamReader(System.in));

        int n = nextInt();
        int m = nextInt();
        String[] st = new String[n];
        int tr = 0, bomb = 0, sx = 0, sy = 0;
        int[] tx = new int [10];
        int[] ty = new int [10];
        int[] bx = new int [10];
        int[] by = new int [10];
        for(int i = 0; i < n; ++i) {
            st[i] = next();
            for(int j = 0; j < m; ++j) {
                char ch = st[i].charAt(j);
                if (ch >= '0' && ch <= '9') {
                    tx[ch - '0' - 1] = i;
                    ty[ch - '0' - 1] = j;
                    ++tr;
                }
                if (ch == 'B') {
                    bx[bomb] = i;
                    by[bomb] = j;
                    ++bomb;
                }
                if (ch == 'S') {
                    sx = i;
                    sy = j;
                }
            }
        }
        int[] cost = new int [tr];
        for(int i = 0; i < tr; ++i) {
            cost[i] = nextInt();
        }
        final int INF = Integer.MAX_VALUE;
        int[][][][] dist = new int [n][m][1 << tr][1 << bomb];
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < m; ++j) {
                for(int t = 0; t < 1 << tr; ++t) {
                    for(int b = 0; b < 1 << bomb; ++b) {
                        dist[i][j][t][b] = INF;
                    }
                }
            }
        }
        dist[sx][sy][0][0] = 0;
        int[] Q = new int[20 * 20 * (1 << tr) * (1 << bomb) * 4];
        int l = 0,r = 0;
        Q[r++] = sx;
        Q[r++] = sy;
        Q[r++] = 0;
        Q[r++] = 0;

        final int[] dx = {1, 0, -1, 0};
        final int[] dy = {0, 1, 0, -1};

        while(l < r) {
            int x = Q[l++];
            int y = Q[l++];
            int t = Q[l++];
            int b = Q[l++];

            for(int d = 0; d < 4; ++d) {
                int nx = x + dx[d];
                int ny = y + dy[d];
                if (nx < 0 || ny < 0 || nx >= n || ny >= m) {
                    continue;
                }
                if (st[nx].charAt(ny) == '.' || st[nx].charAt(ny) == 'S') {
                    int nt = t;
                    int nb = b;
                    for(int i = 0; i < tr; ++i) {
                        if (intersects(tx[i], ty[i], x, y, nx, ny)) {
                            nt ^= (1 << i);
                        }
                    }
                    for(int i = 0; i < bomb; ++i) {
                        if (intersects(bx[i], by[i], x, y, nx, ny)) {
                            nb ^= (1 << i);
                        }
                    }
                    if (dist[nx][ny][nt][nb] == INF) {
                        dist[nx][ny][nt][nb] = dist[x][y][t][b] + 1;
                        Q[r++] = nx;
                        Q[r++] = ny;
                        Q[r++] = nt;
                        Q[r++] = nb;
                    }
                }
            }
        }

        int ans = 0;

        for(int t = 0; t < 1 << tr; ++t) {
            int d = dist[sx][sy][t][0];
            if (d == INF) {
                continue;
            }
            int cur = 0;
            for(int j = 0; j < tr; ++j) {
                if (((t >> j) & 1) == 1) {
                    cur += cost[j];
                }
            }
            ans = Math.max(ans, cur - d);
        }

        System.out.println(ans);
    }

    final double eps = 1e-7;

    boolean intersects(int sx, int sy, int ax, int ay, int bx, int by) {
        // (42, 43) ray from (sx, sy)

        int a1 = 43;
        int b1 = -42;
        int c1 = (sx + 42) * sy - sx * (sy + 43);

        int a2 = by - ay;
        int b2 = ax - bx;
        int c2 = bx * ay - ax * by;

        double det = a1 * b2 - a2 * b1;
        double detx = b1 * c2 - b2 * c1;
        double dety = a2 * c1 - c2 * a1;
        detx /= det;
        dety /= det;
        return detx > Math.min(ax, bx) - eps && detx < Math.max(ax, bx) + eps
                && dety > Math.min(ay, by) - eps && dety < Math.max(ay, by) + eps
                && detx > sx;
    }

    String next() throws IOException {
        if (tok == null || !tok.hasMoreTokens()) {
            tok = new StringTokenizer(in.readLine());
        }
        return tok.nextToken();
    }

    int nextInt() throws IOException {
        return parseInt(next());
    }

    long nextLong() throws IOException {
        return parseLong(next());
    }

    double nextDouble() throws IOException {
        return parseDouble(next());
    }
}


import java.io.*;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.sql.Time;
import java.util.*;

import java.math.BigInteger;

import static java.lang.Math.*;
import static java.math.BigInteger.*;
import static java.util.Arrays.*;

public class Main{

    void run(){
        Locale.setDefault(Locale.US);
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
//        boolean oj = true;
        try{
            if( oj ){
                sc  = new FastScanner( new InputStreamReader(System.in  ) );
                out = new PrintWriter(   new OutputStreamWriter(System.out) );
            } else{
                sc  = new FastScanner(new FileReader("in.txt") );
//                sc  = new FastScanner(new FileReader("D:\\JavaOlymp\\FatalError\\output.txt") );
                out = new PrintWriter(   new FileWriter("out.txt") );
            }
        } catch (Exception e) {
            System.exit(-1);
        }
        long tB = System.currentTimeMillis();
        solve();
        if( !oj ) System.err.println( "Time: " + (System.currentTimeMillis()-tB)/1e3 );
        out.flush();
    }

    class FastScanner{
        BufferedReader br;
        StringTokenizer st = new StringTokenizer("");
        FastScanner( InputStreamReader a ){
            br = new BufferedReader(a);
        }
        FastScanner( FileReader a ){
            br = new BufferedReader(a);
        }
        String next(){
            while( !st.hasMoreTokens() )
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    return null;
                }
            return st.nextToken();
        }
        String readLine(){
            try {
                return br.readLine();
            } catch (Exception e) {
                return null;
            }
        }
        int nextInt(){ return Integer.parseInt(next()); }
        long nextLong(){ return Long.parseLong(next()); }
    }

    FastScanner sc;
    PrintWriter out;

    public static void main(String[] args){
        new Main().run();
//        new Thread( null, new Runnable() {
//            @Override
//            public void run() {
//                new Main().run();
//            }
//            }, "LOL", 256L * 1024 * 1024 / 2 ).run();
//        }, "LOL", 2000 * 1024 * 1024 ).run();
    }

    void TLE(){ for(;;); }

    void MLE(){
        int[][] adj = new int[1024*1024][];
        for( int i = 0; i < adj.length; ++i )
            adj[i] = new int[1024*1024];
    }

    void exit( int val ){
        out.flush();
        System.exit(val);
    }
    //////////////////////////////////////////////////////////////////////////////////////////

    class Item{
        int i, j, msk;
        Item( int _i, int _j, int _msk ){
            i = _i;
            j = _j;
            msk = _msk;
        }
    }

    final int inf = Integer.MAX_VALUE / 10;
    int n, m, Si, Sj;
    char[][] gr;

    int timer, mskOfBomb;
    int[] idObj;

    int[] cost = new int[9];
    int[][] dp;
    int[][] howI = new int[1000][1000];
    int[][] howJ = new int[1000][1000];
    int[][] howM = new int[1000][1000];
    {
        for( int i = 0; i < 1000; ++i ){
            fill( howI[i], -1 );
            fill( howJ[i], -1 );
            fill( howM[i], -1 );
        }
    }

    void f( int i, int j, int msk ){
        if( i==Si && j==Sj && msk==0 ){
        }
        else{
            f(
                howI[i*m+j][msk],
                howJ[i*m+j][msk],
                howM[i*m+j][msk]);
        }
        out.printf("%d %d %4s\n", i, j, Integer.toBinaryString(msk));
    }

    void solve(){
        n = sc.nextInt();
        m = sc.nextInt();
        gr = new char[n][];
        idObj = new int[n*m]; fill( idObj, -1 );
        for( int i = 0; i < n; ++i )
            gr[i] = sc.next().toCharArray();

        int[] tmp = new int[9];
        for( int i = 1; ; ++i )
            try {
                tmp[i] = sc.nextInt();
            } catch (Exception e) {
                break;
            }

        for( int i = 0; i < n; ++i ){
            for( int j = 0; j < m; ++j ){
                char c = gr[i][j];
                if( Character.isDigit(c) ){
                    idObj[i*m+j] = timer++;
                    cost[timer-1] = tmp[c - '0'];
                }
                if( c=='B' ){
                    idObj[i*m+j] = timer++;
                    mskOfBomb |= 1 << (timer-1);
                }
                if( c == 'S' ){
                    Si = i;
                    Sj = j;
                }
            }
        }

        dp = new int[n*m][1<<8];
        for( int[] dpi : dp ) fill( dpi, inf );
        dp[Si*m + Sj][0] = 0;
        ArrayDeque<Item> Q = new ArrayDeque<Item>();
        Q.add(new Item(Si,Sj,0));
        while( !Q.isEmpty() ){
            Item v = Q.pollFirst();
            for( int di = -1; di <= 1; ++di ){
            for( int dj = -1; dj <= 1; ++dj ){
                if( abs(di) + abs(dj) != 1 ) continue;
                Item to = new Item(v.i+di, v.j+dj, v.msk);
                if(!( 0<=to.i && to.i<n &&
                      0<=to.j && to.j<m &&
                      (gr[to.i][to.j] == '.' || gr[to.i][to.j]=='S') ))
                    continue;
                if( abs(di)==1 ){
                    int curI = min(v.i, to.i);
                    for( int k = 0; k < v.j; ++k ){
                        int id = idObj[curI*m + k];
                        if( id != -1 ) to.msk ^= 1 << id;
                    }
                }
                if( dp[to.i*m + to.j][to.msk] > dp[v.i*m + v.j][v.msk] + 1 ){
                    dp[to.i*m + to.j][to.msk] = dp[v.i*m + v.j][v.msk] + 1;
                    Q.addLast(to);
                    howI[to.i*m + to.j][to.msk] = v.i;
                    howJ[to.i*m + to.j][to.msk] = v.j;
                    howM[to.i*m + to.j][to.msk] = v.msk;
                }
            }
            }
        }

        int ans = 0;
        for( int msk = 0; msk < 1<<8; ++msk ){
            if( (msk & mskOfBomb) == 0 &&
                    dp[Si*m + Sj][msk] != inf ){
                int cost = 0;
                for( int i = 0; i < 8; ++i )
                    if( (msk & (1<<i)) != 0 )
                        cost += this.cost[i];
                ans = max( ans, cost - dp[Si*m + Sj][msk] );
            }
        }

        out.println(ans);
    }

}


//package round221;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Queue;

public class C {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), m = ni();
		char[][] map = nm(n,m);
		int sr = -1, sc = -1;
		int[][] objs = new int[8][];
		int p = 0;
		int max = 0;
		for(int i = 0;i < n;i++){
			for(int j = 0;j < m;j++){
				if(map[i][j] == 'S'){
					sr = i; sc = j;
					map[sr][sc] = '.';
				}
				if(map[i][j] >= '1' && map[i][j] <= '9'){
					objs[p++] = new int[]{i, j, map[i][j]-'0'};
					max = Math.max(max, map[i][j]-'0');
				}
				if(map[i][j] == 'B'){
					objs[p++] = new int[]{i, j, -99999};
				}
			}
		}
		int[] price = na(max);
		for(int i = 0;i < p;i++){
			if(objs[i][2] >= 0){
				objs[i][2] = price[objs[i][2]-1];
			}
		}

		int I = 999999;
		int[][][] d = new int[n][m][1<<p];
		for(int i = 0;i < n;i++){
			for(int j = 0;j < m;j++){
				Arrays.fill(d[i][j], I);
			}
		}
		d[sr][sc][0] = 0;
		Queue<Integer> q = new ArrayDeque<Integer>();
		q.add(enc(sr, sc, 0));
		int[] dr = { 1, 0, -1, 0 };
		int[] dc = { 0, 1, 0, -1 };
		while(!q.isEmpty()){
			int cur = q.poll();
			int r = cur>>>5&31, c = cur&31, ptn = cur>>>10;
			for(int k = 0;k < 4;k++){
				int nr = r + dr[k], nc = c + dc[k];
				if(nr >= 0 && nr < n && nc >= 0 && nc < m && map[nr][nc] == '.'){
					int nptn = ptn;
					if(k == 2){
						for(int u = 0;u < p;u++){
							if(objs[u][0] == r && objs[u][1] < c)nptn ^= 1<<u;
						}
					}
					if(k == 0){
						for(int u = 0;u < p;u++){
							if(objs[u][0] == nr && objs[u][1] < nc)nptn ^= 1<<u;
						}
					}
					if(d[nr][nc][nptn] > d[r][c][ptn] + 1){
						d[nr][nc][nptn] = d[r][c][ptn] + 1;
						q.add(enc(nr, nc, nptn));
					}
				}
			}
		}

		long ret = 0;
		for(int i = 0;i < 1<<p;i++){
			long tot = 0;
			for(int j = 0;j < p;j++){
				if(i<<31-j<0){
					tot += objs[j][2];
				}
			}
			ret = Math.max(ret, tot - d[sr][sc][i]);
		}
		out.println(ret);
	}

	int enc(int r, int c, int ptn)
	{
		return ptn<<10|r<<5|c;
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new C().run(); }

	private byte[] inbuf = new byte[1024];
	private int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


//package codeforces;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class C {
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter writer = new PrintWriter(System.out);
    StringTokenizer stringTokenizer;

    String next() throws IOException {
        while (stringTokenizer == null || !stringTokenizer.hasMoreTokens()) {
            stringTokenizer = new StringTokenizer(reader.readLine());
        }
        return stringTokenizer.nextToken();
    }

    int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    long nextLong() throws IOException {
        return Long.parseLong(next());
    }

    void solve() throws IOException {
        int n = nextInt();
        int m = nextInt();
        char[][] map = new char[n][];
        int bombs = 0;
        int treasures = 0;
        for (int i = 0; i < n; i++) {
            map[i] = next().toCharArray();
            for (int j = 0; j < m; j++) {
                if (map[i][j] == 'B') bombs++;
                if (map[i][j] >= '0' && map[i][j] <= '9') {
                    treasures++;
                    map[i][j]--;
                }
            }
        }
        int[] treasureCosts = new int[treasures];
        for (int i = 0; i < treasures; i++) {
            treasureCosts[i] = nextInt();
        }
        class Point {
            int x, y;

            Point(int x, int y) {
                this.x = x;
                this.y = y;
            }

            Point subtract(Point other) {
                return new Point(x - other.x, y - other.y);
            }

            int vectorProduct(Point other) {
                return x * other.y - y * other.x;
            }

            Point add(Point other) {
                return new Point(x + other.x, y + other.y);
            }
        }
        class GeomUtils {
            Point cellCenter(int row, int column) {
                return new Point(2 * row + 1, 2 * column + 1);
            }

            Point ray = new Point(40, 41);

            double getT(Point o, Point v, Point s1, Point s2) {
                Point vs = s2.subtract(s1);
                int r = vs.vectorProduct(s2) - vs.vectorProduct(o);
                int l = vs.vectorProduct(v);
                return 1.0 * r / l;
            }

            boolean intersects(Point o, Point s1, Point s2) {
                if (getT(o, ray, s1, s2) < 0.0) return false;
                double t = getT(s1, s2.subtract(s1), o, o.add(ray));
                return t >= 0.0 && t <= 1.0;
            }
        }
        Point[] treasureCoords = new Point[treasures];
        Point[] bombCoords = new Point[bombs];
        bombs = 0;
        int si = 0, sj = 0;
        GeomUtils geomUtils = new GeomUtils();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (map[i][j] == 'B') {
                    bombCoords[bombs++] = geomUtils.cellCenter(i, j);
                }
                if (map[i][j] >= '0' && map[i][j] <= '9') {
                    treasureCoords[map[i][j] - '0'] = geomUtils.cellCenter(i, j);
                }
                if (map[i][j] == 'S') {
                    si = i;
                    sj = j;
                }
            }
        }
        int[][][][] dist = new int[n][m][1 << treasures][1 << bombs];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                for (int k = 0; k < 1 << treasures; k++)
                    for (int l = 0; l < 1 << bombs; l++) dist[i][j][k][l] = Integer.MAX_VALUE;
        dist[si][sj][0][0] = 0;
        Queue<Integer> qi = new LinkedList<>(), qj = new LinkedList<>(), qt = new LinkedList<>(), qb = new LinkedList<>();
        qi.add(si);
        qj.add(sj);
        qt.add(0);
        qb.add(0);
        int[] di = {0, -1, 0, 1};
        int[] dj = {-1, 0, 1, 0};
        while (!qi.isEmpty()) {
            int i = qi.poll();
            int j = qj.poll();
            int tmask = qt.poll();
            int bmask = qb.poll();
            Point s1 = geomUtils.cellCenter(i, j);
            for (int k = 0; k < 4; k++) {
                int ii = i + di[k];
                int jj = j + dj[k];
                if (ii < 0 || ii >= n || jj < 0 || jj >= m || map[ii][jj] != '.' && map[ii][jj] != 'S') continue;
                int tm = 0;
                for (int ti = 0; ti < treasures; ti++) {
                    if (geomUtils.intersects(treasureCoords[ti], s1, geomUtils.cellCenter(ii, jj))) {
                        tm |= 1 << ti;
                    }
                }
                int bm = 0;
                for (int bi = 0; bi < bombs; bi++) {
                    if (geomUtils.intersects(bombCoords[bi], s1, geomUtils.cellCenter(ii, jj))) {
                        bm |= 1 << bi;
                    }
                }
                if (dist[ii][jj][tmask ^ tm][bmask ^ bm] == Integer.MAX_VALUE) {
                    dist[ii][jj][tmask ^ tm][bmask ^ bm] = dist[i][j][tmask][bmask] + 1;
                    qi.add(ii);
                    qj.add(jj);
                    qt.add(tmask ^ tm);
                    qb.add(bmask ^ bm);
                }
            }
        }
        int ans = 0;
        for (int i = 0; i < 1 << treasures; i++) {
            if(dist[si][sj][i][0] == Integer.MAX_VALUE) continue;
            int tCost = 0;
            for (int j = 0; j < treasures; j++) {
                if (((i >> j) & 1) == 1) tCost += treasureCosts[j];
            }
            ans = Math.max(ans, tCost - dist[si][sj][i][0]);
        }
        writer.println(ans);
        writer.close();
    }

    public static void main(String[] args) throws IOException {
        new C().solve();
    }
}


import java.io.*;
import java.util.*;

public class Main implements Runnable {

	public void _main() throws IOException {
		final int infinity = 1000000000;
		// A ray that is not collinear with any of the (dx, dy)`s
		final int RAY_R = 31;
		final int RAY_C = 37;
		int height = nextInt();
		int width = nextInt();
		char[][] s = new char[height][];
		int sr = -1;
		int sc = -1;
		int numTreasures = 0;
		int numBombs = 0;
		int[][] treasureId = new int[height][width];
		int[][] bombId = new int[height][width];
		for (int r = 0; r < height; r++) {
			s[r] = next().toCharArray();
			for (int c = 0; c < width; c++) {
				if (s[r][c] == 'S') {
					sr = r;
					sc = c;
					s[r][c] = '.';
				}
				treasureId[r][c] = -1;
				if (Character.isDigit(s[r][c])) {
					treasureId[r][c] = s[r][c] - '1';
					++numTreasures;
				}
				bombId[r][c] = -1;
				if (s[r][c] == 'B') {
					bombId[r][c] = numBombs;
					++numBombs;
				}
			}
		}
		int[] treasureR = new int[numTreasures];
		int[] treasureC = new int[numTreasures];
		int[] bombR = new int[numBombs];
		int[] bombC = new int[numBombs];
		for (int r = 0; r < height; r++) {
			for (int c = 0; c < width; c++) {
				if (treasureId[r][c] >= 0) {
					int id = treasureId[r][c];
					treasureR[id] = r;
					treasureC[id] = c;
				}
				if (bombId[r][c] >= 0) {
					int id = bombId[r][c];
					bombR[id] = r;
					bombC[id] = c;
				}
			}
		}
		int[] cost = new int[numTreasures];
		for (int i = 0; i < numTreasures; i++) {
			cost[i] = nextInt();
		}
		int[] value = new int[1 << (numTreasures + numBombs)];
		for (int i = 1; i < value.length; i++) {
			int j = Integer.numberOfTrailingZeros(i);
			if (j < numTreasures) {
				value[i] = cost[j] + value[i ^ (1 << j)];
			} else {
				value[i] = -infinity;
			}
		}
		int qsize = height * width * (1 << (numTreasures + numBombs));
		int[] qr = new int[qsize];
		int[] qc = new int[qsize];
		int[] qmask = new int[qsize];
		int[][][] dist = new int[height][width][1 << (numTreasures + numBombs)];
		for (int r = 0; r < height; r++) {
			for (int c = 0; c < width; c++) {
				Arrays.fill(dist[r][c], infinity);
			}
		}
		dist[sr][sc][0] = 0;
		qr[0] = sr;
		qc[0] = sc;
		qmask[0] = 0;
		int qt = 0;
		int qh = 1;
		int ans = 0;
		while (qt < qh) {
			int r = qr[qt];
			int c = qc[qt];
			int mask = qmask[qt];
			++qt;
			if (r == sr && c == sc) {
				ans = Math.max(ans, value[mask] - dist[r][c][mask]);
			}
			for (int dr = -1; dr <= 1; dr++) {
				for (int dc = -1; dc <= 1; dc++) {
					if (dr == 0 ^ dc == 0) {
						int nr = r + dr;
						int nc = c + dc;
						if (nr < 0 || nr >= height || nc < 0 || nc >= width) continue;
						if (s[nr][nc] != '.') continue;
						int nmask = mask;
						for (int i = 0; i < numTreasures + numBombs; i++) {
							int or, oc;
							if (i < numTreasures) {
								or = treasureR[i];
								oc = treasureC[i];
							} else {
								or = bombR[i - numTreasures];
								oc = bombC[i - numTreasures];
							}
							int r1 = r - or;
							int c1 = c - oc;
							int r2 = nr - or;
							int c2 = nc - oc;
							if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0) continue;
							if (Integer.signum(cross(r1, c1, RAY_R, RAY_C)) == Integer.signum(cross(RAY_R, RAY_C, r2, c2))) {
								nmask ^= 1 << i;
							}
						}
						if (dist[nr][nc][nmask] > 1 + dist[r][c][mask]) {
							dist[nr][nc][nmask] = 1 + dist[r][c][mask];
							qr[qh] = nr;
							qc[qh] = nc;
							qmask[qh] = nmask;
							++qh;
						}
					}
				}
			}
		}
		out.println(ans);
	}

	private int cross(int x1, int y1, int x2, int y2) {
		return x1*y2 - x2*y1;
	}

	private BufferedReader in;
	private PrintWriter out;
	private StringTokenizer st;

	private String next() throws IOException {
		while (st == null || !st.hasMoreTokens()) {
			String rl = in.readLine();
			if (rl == null)
				return null;
			st = new StringTokenizer(rl);
		}
		return st.nextToken();
	}

	private int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	private long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	private double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}

	public static void main(String[] args) {
		Locale.setDefault(Locale.UK);
		new Thread(new Main()).start();
	}

	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			//in = new BufferedReader(new FileReader("a.in"));
			//out = new PrintWriter(new FileWriter("a.out"));

			_main();

			out.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(202);
		}
	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

/**
 * @author Don Li
 */
public class CirclingRoundTreasures {

    int INF = (int) 1e7;

    int[] dx = new int[]{-1, 0, 0, 1};
    int[] dy = new int[]{0, -1, 1, 0};

    void solve() {
        int n = in.nextInt(), m = in.nextInt();
        char[][] s = new char[n][];
        for (int i = 0; i < n; i++) s[i] = in.nextToken().toCharArray();

        int t = 0, b = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (s[i][j] >= '1' && s[i][j] <= '8') t++;
                else if (s[i][j] == 'B') b++;
            }
        }

        int[] v = new int[t + b];
        for (int i = 0; i < t; i++) v[i] = in.nextInt();

        int sx = -1, sy = -1;
        int[] X = new int[t + b], Y = new int[t + b];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (s[i][j] >= '1' && s[i][j] <= '8') {
                    int id = s[i][j] - '1';
                    X[id] = i;
                    Y[id] = j;
                } else if (s[i][j] == 'B') {
                    X[t] = i;
                    Y[t] = j;
                    v[t] = -INF;
                    t++;
                } else if (s[i][j] == 'S') {
                    sx = i;
                    sy = j;
                }
            }
        }

        int[] cost = new int[1 << t];
        for (int i = 0; i < 1 << t; i++) {
            for (int j = 0; j < t; j++) {
                if ((i & (1 << j)) > 0) cost[i] += v[j];
            }
        }

        int[][][] dp = new int[n][m][1 << t];
        for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) Arrays.fill(dp[i][j], INF);

        int ans = 0;
        Queue<int[]> qu = new LinkedList<>();
        qu.offer(new int[]{sx, sy, 0});
        dp[sx][sy][0] = 0;
        while (!qu.isEmpty()) {
            int[] a = qu.poll();
            int x = a[0], y = a[1], mask = a[2];
            if (x == sx && y == sy) {
                ans = Math.max(ans, cost[mask] - dp[x][y][mask]);
            }
            for (int i = 0; i < 4; i++) {
                int nx = x + dx[i], ny = y + dy[i];
                if (nx >= 0 && nx < n && ny >= 0 && ny < m && (s[nx][ny] == '.' || s[nx][ny] == 'S')) {
                    int nmask = mask;
                    for (int j = 0; j < t; j++) {
                        if (cross(x, y, nx, ny, X[j], Y[j])) nmask ^= 1 << j;
                    }
                    if (dp[nx][ny][nmask] > dp[x][y][mask] + 1) {
                        dp[nx][ny][nmask] = dp[x][y][mask] + 1;
                        qu.offer(new int[]{nx, ny, nmask});
                    }
                }
            }
        }
        out.println(ans);
    }

    boolean cross(int x1, int y1, int x2, int y2, int x, int y) {
        return x == x1 && y < y1 && x == x2 + 1 && y < y2 || x == x2 && y < y2 && x == x1 + 1 && y < y1;
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new CirclingRoundTreasures().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }

        public long nextLong() {
            return Long.parseLong(nextToken());
        }

        public double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}


import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Arrays;

public class CF1153F {
    public static void main(String[] args) throws Exception {
        boolean local = System.getProperty("ONLINE_JUDGE") == null;
        boolean async = false;

        Charset charset = Charset.forName("ascii");

        FastIO io = local ? new FastIO(new FileInputStream("D:\\DATABASE\\TESTCASE\\Code.in"), System.out, charset) : new FastIO(System.in, System.out, charset);
        Task task = new Task(io, new Debug(local));

        if (async) {
            Thread t = new Thread(null, task, "dalt", 1 << 27);
            t.setPriority(Thread.MAX_PRIORITY);
            t.start();
            t.join();
        } else {
            task.run();
        }

        if (local) {
            io.cache.append("\n\n--memory -- \n" + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20) + "M");
        }

        io.flush();
    }

    public static class Task implements Runnable {
        final FastIO io;
        final Debug debug;
        int inf = (int) 1e8;
        int mod = 998244353;
        int[][][] mem;
        boolean[][][] visit;
        int l1;
        int l2;
        int l3;
        int n;
        int k;
        int time;

        public Task(FastIO io, Debug debug) {
            this.io = io;
            this.debug = debug;
        }

        @Override
        public void run() {
            solve();
        }

        public void solve() {
            n = io.readInt();
            k = io.readInt();
            int l = io.readInt();
            mem = new int[2][n + 1][n + 1];
            visit = new boolean[2][n + 1][n + 1];
            int meetCount = find(n, n, 1);

            int factorial = 1;
            for (int i = 2, until = 2 * n + 1; i <= until; i++) {
                factorial = mul(factorial, i);
            }
            int total = mul(factorial, Mathematics.inverse(Mathematics.pow(2, n, mod), mod));
            int probability = mul(meetCount, Mathematics.inverse(total, mod));
            int expectLength = mul(l, probability);
            io.cache.append(expectLength);
        }

        public int add(int a, int b) {
            return (a + b) % mod;
        }

        public int sub(int a, int b) {
            if (a >= b) {
                return a - b;
            }
            return a - b + mod;
        }

        public int mul(int a, int b) {
            return (int) (((long) a * b) % mod);
        }

        public int find(int i, int j, int x) {
            time++;
            if (i < 0 || i > n || j < 0 || j > n) {
                return 0;
            }
            if (i == 0 && j == 0 && x == 0) {
                return 1;
            }
            if (visit[x][i][j]) {
                return mem[x][i][j];
            }
            visit[x][i][j] = true;
            mem[x][i][j] = 0;
            if (i < j) {
                return 0;
            }
            if (x == 1) {
                mem[x][i][j] = (mem[x][i][j] + find(i, j, 0) * (i - j >= k ? 1 : 0)) % mod;
            }
            mem[x][i][j] = (int) ((mem[x][i][j] + (long) (n - i + 1) * find(i - 1, j, x)) % mod);
            mem[x][i][j] = (int)((mem[x][i][j] + (long)(i - j + 1) * find(i, j - 1, x)) % mod);
            return mem[x][i][j];
        }
    }

    public static class Mathematics {

        public static int ceilPowerOf2(int x) {
            return 32 - Integer.numberOfLeadingZeros(x - 1);
        }

        public static int floorPowerOf2(int x) {
            return 31 - Integer.numberOfLeadingZeros(x);
        }

        public static long modmul(long a, long b, long mod) {
            return b == 0 ? 0 : ((modmul(a, b >> 1, mod) << 1) % mod + a * (b & 1)) % mod;
        }

        /**
         * Get the greatest common divisor of a and b
         */
        public static int gcd(int a, int b) {
            return a >= b ? gcd0(a, b) : gcd0(b, a);
        }

        private static int gcd0(int a, int b) {
            return b == 0 ? a : gcd0(b, a % b);
        }

        public static int extgcd(int a, int b, int[] coe) {
            if (a >= b) {
                return extgcd0(a, b, coe);
            } else {
                int g = extgcd0(b, a, coe);
                int tmp = coe[0];
                coe[0] = coe[1];
                coe[1] = tmp;
                return g;
            }
        }

        private static int extgcd0(int a, int b, int[] coe) {
            if (b == 0) {
                coe[0] = 1;
                coe[1] = 0;
                return a;
            }
            int g = extgcd0(b, a % b, coe);
            int n = coe[0];
            int m = coe[1];
            coe[0] = m;
            coe[1] = n - m * (a / b);
            return g;
        }

        /**
         * Get the greatest common divisor of a and b
         */
        public static long gcd(long a, long b) {
            return a >= b ? gcd0(a, b) : gcd0(b, a);
        }

        private static long gcd0(long a, long b) {
            return b == 0 ? a : gcd0(b, a % b);
        }

        public static long extgcd(long a, long b, long[] coe) {
            if (a >= b) {
                return extgcd0(a, b, coe);
            } else {
                long g = extgcd0(b, a, coe);
                long tmp = coe[0];
                coe[0] = coe[1];
                coe[1] = tmp;
                return g;
            }
        }

        private static long extgcd0(long a, long b, long[] coe) {
            if (b == 0) {
                coe[0] = 1;
                coe[1] = 0;
                return a;
            }
            long g = extgcd0(b, a % b, coe);
            long n = coe[0];
            long m = coe[1];
            coe[0] = m;
            coe[1] = n - m * (a / b);
            return g;
        }

        /**
         * Get y where x * y = 1 (% mod)
         */
        public static int inverse(int x, int mod) {
            return pow(x, mod - 2, mod);
        }

        /**
         * Get x^n(% mod)
         */
        public static int pow(int x, int n, int mod) {
            n = mod(n, mod - 1);
            x = mod(x, mod);
            int bit = 31 - Integer.numberOfLeadingZeros(n);
            long product = 1;
            for (; bit >= 0; bit--) {
                product = product * product % mod;
                if (((1 << bit) & n) != 0) {
                    product = product * x % mod;
                }
            }
            return (int) product;
        }

        public static long longpow(long x, long n, long mod) {
            if (n == 0) {
                return 1;
            }
            long prod = longpow(x, n >> 1, mod);
            prod = modmul(prod, prod, mod);
            if ((n & 1) == 1) {
                prod = modmul(prod, x, mod);
            }
            return prod;
        }

        /**
         * Get x % mod
         */
        public static int mod(int x, int mod) {
            return x >= 0 ? x % mod : (((x % mod) + mod) % mod);
        }

        /**
         * Get n!/(n-m)!
         */
        public static long permute(int n, int m) {
            return m == 0 ? 1 : n * permute(n - 1, m - 1);
        }

        /**
         * Put all primes less or equal to limit into primes after offset
         */
        public static int eulerSieve(int limit, int[] primes, int offset) {
            boolean[] isComp = new boolean[limit + 1];
            int wpos = offset;
            for (int i = 2; i <= limit; i++) {
                if (!isComp[i]) {
                    primes[wpos++] = i;
                }
                for (int j = offset, until = limit / i; j < wpos && primes[j] <= until; j++) {
                    int pi = primes[j] * i;
                    isComp[pi] = true;
                    if (i % primes[j] == 0) {
                        break;
                    }
                }
            }
            return wpos - offset;
        }

        /**
         * Round x into integer
         */
        public static int intRound(double x) {
            if (x < 0) {
                return -(int) (-x + 0.5);
            }
            return (int) (x + 0.5);
        }

        /**
         * Round x into long
         */
        public static long longRound(double x) {
            if (x < 0) {
                return -(long) (-x + 0.5);
            }
            return (long) (x + 0.5);
        }
    }

    public static class FastIO {
        public final StringBuilder cache = new StringBuilder();
        private final InputStream is;
        private final OutputStream os;
        private final Charset charset;
        private StringBuilder defaultStringBuf = new StringBuilder(1 << 8);
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastIO(InputStream is, OutputStream os, Charset charset) {
            this.is = is;
            this.os = os;
            this.charset = charset;
        }

        public FastIO(InputStream is, OutputStream os) {
            this(is, os, Charset.forName("ascii"));
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public long readLong() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            long val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public double readDouble() {
            boolean sign = true;
            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+';
                next = read();
            }

            long val = 0;
            while (next >= '0' && next <= '9') {
                val = val * 10 + next - '0';
                next = read();
            }
            if (next != '.') {
                return sign ? val : -val;
            }
            next = read();
            long radix = 1;
            long point = 0;
            while (next >= '0' && next <= '9') {
                point = point * 10 + next - '0';
                radix = radix * 10;
                next = read();
            }
            double result = val + (double) point / radix;
            return sign ? result : -result;
        }

        public String readString(StringBuilder builder) {
            skipBlank();

            while (next > 32) {
                builder.append((char) next);
                next = read();
            }

            return builder.toString();
        }

        public String readString() {
            defaultStringBuf.setLength(0);
            return readString(defaultStringBuf);
        }

        public int readLine(char[] data, int offset) {
            int originalOffset = offset;
            while (next != -1 && next != '\n') {
                data[offset++] = (char) next;
                next = read();
            }
            return offset - originalOffset;
        }

        public int readString(char[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (char) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public int readString(byte[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (byte) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public char readChar() {
            skipBlank();
            char c = (char) next;
            next = read();
            return c;
        }

        public void flush() {
            try {
                os.write(cache.toString().getBytes(charset));
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public boolean hasMore() {
            skipBlank();
            return next != -1;
        }
    }

    public static class Debug {
        private boolean allowDebug;

        public Debug(boolean allowDebug) {
            this.allowDebug = allowDebug;
        }

        public void assertTrue(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (!flag) {
                fail();
            }
        }

        public void fail() {
            throw new RuntimeException();
        }

        public void assertFalse(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (flag) {
                fail();
            }
        }

        private void outputName(String name) {
            System.out.print(name + " = ");
        }

        public void debug(String name, int x) {
            if (!allowDebug) {
                return;
            }

            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, long x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, double x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, int[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, long[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, double[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, Object x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, Object... x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.deepToString(x));
        }
    }
}


// upsolve with rainboy
import java.io.*;
import java.util.*;

public class CF1153F {
	static final int MD = 998244353;
	static int[][] ch;
	static void init(int n) {
		ch = new int[1 + n][1 + n];
		ch[0][0] = 1;
		for (int i = 1; i <= n; i++) {
			ch[i][0] = 1;
			for (int j = 1; j <= i; j++)
				ch[i][j] = (ch[i - 1][j] + ch[i - 1][j - 1]) % MD;
		}
	}
	static long power(int a, int k) {
		if (k == 0)
			return 1;
		long p = power(a, k / 2);
		p = p * p % MD;
		if (k % 2 == 1)
			p = p * a % MD;
		return p;
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int k = Integer.parseInt(st.nextToken());
		int l = Integer.parseInt(st.nextToken());
		init(n);
		long[] pp = new long[1 + n + n];
		long[] qq = new long[1 + n + n];
		pp[n] = power(2, n);
		for (int i = 0; i < n; i++)
			for (int j = n + n; j > 0; j--)
				pp[j] = (pp[j] - pp[j - 1]) % MD;
		long[] aa = new long[1 + n + n];
		for (int j = 0; j <= n + n; j++)
			aa[j] = pp[j];
		long inv2 = (MD + 1) / 2;
		for (int i = 1; i <= n - k; i++) {
			// qq := pp / p, where p = 2x (1 - x)
			// divide by 2x
			for (int j = 0; j < n + n; j++)
				qq[j] = pp[j + 1] * inv2 % MD;
			qq[n + n] = 0;
			// divide by 1 - x is multiply by 1 + x + x^2 + x^3 + ...
			for (int j = 1; j <= n + n; j++)
				qq[j] = (qq[j] + qq[j - 1]) % MD;
			// pp := pp * (1 - p) / p = pp / p - pp = qq - pp
			for (int j = 0; j <= n + n; j++)
				pp[j] = (qq[j] - pp[j]) % MD;
			long a = ch[n][i];
			for (int j = 0; j <= n + n; j++)
				aa[j] = (aa[j] + a * pp[j]) % MD;
		}
		// integrate x^i to x^{i + 1} / (i + 1)
		long a = 0;
		for (int i = 0; i <= n + n; i++)
			a = (a + aa[i] * power(i + 1, MD - 2)) % MD;
		a = (a * l % MD + MD) % MD;
		System.out.println(a);
	}
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        F solver = new F();
        solver.solve(1, in, out);
        out.close();
    }

    static class F {
        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int n = in.ni(), k = in.ni(), l = in.ni();
            int mod = 998244353;
            long[] invs = IntegerUtils.invs(2 * n + 3, mod);
            long[][] p = new long[2 * n + 1][n + 1];
            p[0][1] = 1; // first is always started
            for (int i = 1; i < 2 * n; i++) {
                int prevMaxRunning = Math.min(2 * n - i, i); // how many intervals max were running (covering)
                int maxRunning = Math.min(2 * n - i - 1, i + 1); // how many intervals max can be running
                for (int j = 0; j <= prevMaxRunning; j++) {
                    if (p[i - 1][j] != 0) {
                        if (j > 0) {
                            p[i][j - 1] = (p[i][j - 1] + p[i - 1][j] * j % mod * invs[2 * n - i] % mod) % mod; // close an interval
                        }
                        if (j < maxRunning) {
                            p[i][j + 1] = (p[i][j + 1] + p[i - 1][j] * (2 * n - i - j) % mod * invs[2 * n - i] % mod) % mod; // start a new interval
                        }
                    }
                }
            }
            long ans = 0;
            for (int i = 0; i < 2 * n; i++) {
                for (int j = k; j <= n; j++) {
                    if (p[i][j] == 0)
                        continue;
                    ans = (ans + p[i][j]) % mod;
                }
            }
            ans = ans * l % mod * invs[2 * n + 1] % mod;
            out.println(ans);
        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

        public String ns() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    String rl = in.readLine();
                    if (rl == null) {
                        return null;
                    }
                    st = new StringTokenizer(rl);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int ni() {
            return Integer.parseInt(ns());
        }

    }

    static class IntegerUtils {
        public static long[] invs(int n, long p) {
            long[] res = new long[n];
            res[1] = 1;
            for (int i = 2; i < n; i++) {
                res[i] = (p - (p / i) * res[(int) (p % i)] % p) % p;
            }
            return res;
        }

    }
}


import java.io.*;
import java.util.*;

public class Codeforces1153F {

	public static void main(String[] args) throws IOException {
		int P = 998244353;

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int real_k = Integer.parseInt(st.nextToken());
		int l = Integer.parseInt(st.nextToken());

		//generate factorials
		int[] factorials = new int[2*n+2];
		factorials[0] = 1;
		for (int i = 1; i <= 2*n+1; i++) {
			factorials[i] = multiply(factorials[i-1], i, P);
		}

		//number of ways to choose k pairs from 2k elements
		//where order doesn't matter
		//equals (2k)!/(2^n)/k! = (2k-1)!!
		int[] doublefact = new int[n+1];
		doublefact[0] = 1;
		for (int i = 1; i <= n; i++) {
			doublefact[i] = multiply(doublefact[i-1], (2*i-1), P);
		}

		//list[r][k] stores for rth segment, exactly k of the n segments covering it
		int[][] list = new int[2*n+2][n+1];

		for (int r = 1; r <= 2*n+1; r++) {
			for (int k = 1; k <= n; k++) {
				if (((r%2) != (k%2)) && (r-1 >= k) && (2*n+1-r >= k)) {
					int num = multiply(factorials[r-1], factorials[2*n+1-r], P);
					num = multiply(num, doublefact[(r-k-1)/2], P);
					num = multiply(num, doublefact[(2*n+1-r-k)/2], P);

					int denom = multiply(factorials[r-k-1], factorials[2*n+1-r-k], P);
					denom = multiply(denom, factorials[k], P);

					list[r][k] = multiply(num, inverse(multiply(denom, doublefact[n], P), P), P);
				}

			}
		}

		int ans = 0;
		for (int r = 1; r <= 2*n+1; r++) {
			for (int k = real_k; k <= n; k++) {
				ans += list[r][k];
				ans %= P;
			}
		}

		ans = multiply(ans, l, P);
		ans = multiply(ans, inverse(2*n+1, P), P);

		System.out.println(ans);

	}

	public static int multiply (int a, int b, int n) {
		long ab = (long) a * (long) b;
		return ((int) (ab%n));
	}

	public static int inverse (int a, int n) {
		int m = n;
		int r1 = 1;
		int r2 = 0;
		int r3 = 0;
		int r4 = 1;
		while ((a > 0) && (n > 0)) {
			if (n >= a) {
				r3 -= r1*(n/a);
				r4 -= r2*(n/a);
				n = n%a;
			}
			else {
				int tmp = a;
				a = n;
				n = tmp;
				tmp = r1;
				r1 = r3;
				r3 = tmp;
				tmp = r2;
				r2 = r4;
				r4 = tmp;
			}
		}
		if (a == 0) {
			if (r3 >= 0)
				return (r3%m);
			else
				return (m+(r3%m));
		}
		else {
			if (r1 >= 0)
				return (r1%m);
			else
				return (m+(r1%m));
		}

	}

}


//package round551;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class F {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), K = ni(), L = ni();
		int mod = 998244353;
		int[][] fif = enumFIF(10000, mod);
		long[] muls = new long[n+1];
		for(int i = K;i <= n;i++){
			long m = C(n, i, mod, fif);
			for(int j = i;j <= n;j++){
				muls[j] += m * C(n-i, n-j, mod, fif) * ((j-i) % 2 == 0 ? 1 : -1);
				muls[j] %= mod;
			}
		}
		/*
\int_0^1 D(t) * (2x(1-x))^t dx
D(t) *
2^t * (t!)^2 / (2t+1)!
		 *
		 */

		long ans = 0;
		for(int i = K;i <= n;i++){
			ans +=
			pow(2, i, mod) * fif[0][i] % mod * fif[0][i] % mod
			* fif[1][2*i+1] % mod * muls[i];
			ans %= mod;
		}
		if(ans < 0)ans += mod;
		out.println(ans*L%mod);
	}

	public static long C(int n, int r, int mod, int[][] fif) {
		if (n < 0 || r < 0 || r > n)
			return 0;
		return (long) fif[0][n] * fif[1][r] % mod * fif[1][n - r] % mod;
	}

	public static long pow(long a, long n, long mod) {
		//		a %= mod;
		long ret = 1;
		int x = 63 - Long.numberOfLeadingZeros(n);
		for (; x >= 0; x--) {
			ret = ret * ret % mod;
			if (n << 63 - x < 0)
				ret = ret * a % mod;
		}
		return ret;
	}

	public static int[][] enumFIF(int n, int mod) {
		int[] f = new int[n + 1];
		int[] invf = new int[n + 1];
		f[0] = 1;
		for (int i = 1; i <= n; i++) {
			f[i] = (int) ((long) f[i - 1] * i % mod);
		}
		long a = f[n];
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		invf[n] = (int) (p < 0 ? p + mod : p);
		for (int i = n - 1; i >= 0; i--) {
			invf[i] = (int) ((long) invf[i + 1] * (i + 1) % mod);
		}
		return new int[][] { f, invf };
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new F().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        F solver = new F();
        solver.solve(1, in, out);
        out.close();
    }

    static class F {
        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int n = in.ni(), k = in.ni(), l = in.ni();
            int mod = 998244353;
            long[] invs = IntegerUtils.invs(2 * n + 3, mod);
            long[][] p = new long[2 * n + 1][n + 1];
            p[0][1] = 1; // first is always started
            long ans = 0;
            for (int i = 1; i < 2 * n; i++) {
                int prevMaxRunning = Math.min(2 * n - i, i); // how many intervals max were running (covering)
                int maxRunning = Math.min(2 * n - i - 1, i + 1); // how many intervals max can be running
                for (int j = 0; j <= prevMaxRunning; j++) {
                    if (p[i - 1][j] != 0) {
                        if (j > 0) {
                            p[i][j - 1] = (p[i][j - 1] + p[i - 1][j] * j % mod * invs[2 * n - i] % mod) % mod; // close an interval
                        }
                        if (j < maxRunning) {
                            p[i][j + 1] = (p[i][j + 1] + p[i - 1][j] * (2 * n - i - j) % mod * invs[2 * n - i] % mod) % mod; // start a new interval
                        }
                        if (j >= k)
                            ans = (ans + p[i - 1][j]) % mod;
                    }
                }
            }
            if (k <= 1)
                ans += p[2 * n - 1][1];

            ans = ans * l % mod * invs[2 * n + 1] % mod;
            out.println(ans);
        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

        public String ns() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    String rl = in.readLine();
                    if (rl == null) {
                        return null;
                    }
                    st = new StringTokenizer(rl);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int ni() {
            return Integer.parseInt(ns());
        }

    }

    static class IntegerUtils {
        public static long[] invs(int n, long p) {
            long[] res = new long[n];
            res[1] = 1;
            for (int i = 2; i < n; i++) {
                res[i] = (p - (p / i) * res[(int) (p % i)] % p) % p;
            }
            return res;
        }

    }
}


import java.io.*;
import java.util.*;

public class Main implements Runnable{
    public static void main(String[] args){
        //new Thread(null,new Main(),"Thread-1",1024*1024*10).start();
        new Main().run();
    }
    int mod=998244353;
    private void solve() throws Exception {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        int n=in.nextInt(),k=in.nextInt(),l=in.nextInt();
        long[]fac=new long[n+1];
        fac[0]=1;
        for(int i=1;i<=n;i++){
            fac[i]=fac[i-1]*i%mod;
        }
        long[][]dp=new long[2*n+1][2*n+2];
        dp[0][0]=1;
        for(int i=1;i<=2*n;i++){
            for(int j=0;j<=Math.min(i,n);j++){
                if(j>0) dp[i][j]=(dp[i][j]+dp[i-1][j-1])%mod;
                dp[i][j]=(dp[i][j]+dp[i-1][j+1]*(j+1)%mod)%mod;
            }
        }
        long ans=0;
        for(int i=k;i<=2*n;i++){
            for(int j=k;j<=n;j++){
                ans=(ans+dp[i][j]*dp[2*n-i][j]%mod*fac[j]%mod)%mod;
            }
        }
        out.println(l*ans%mod*Pow(dp[2*n][0],mod-2)%mod*Pow(2*n+1,mod-2)%mod);
        out.flush();
    }
    long Pow(long a,long b){
        long ans=1;
        while(b>0){
            if((b&1)!=0)ans=(ans*a)%mod;
            a=(a*a)%mod;
            b>>=1;
        }
        return ans;
    }
    @Override
    public void run() {
        try {
            solve();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    class InputReader{
        StreamTokenizer tokenizer;
        public InputReader(InputStream stream){
            tokenizer=new StreamTokenizer(new BufferedReader(new InputStreamReader(stream)));
            tokenizer.ordinaryChars(33,126);
            tokenizer.wordChars(33,126);
        }
        public String next() throws IOException {
            tokenizer.nextToken();
            return tokenizer.sval;
        }
        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }
        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }
        public boolean hasNext() throws IOException {
            int res=tokenizer.nextToken();
            tokenizer.pushBack();
            return res!=tokenizer.TT_EOF;
        }
    }
}


import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Arrays;

public class CF1153F {
    public static void main(String[] args) throws Exception {
        boolean local = System.getProperty("ONLINE_JUDGE") == null;
        boolean async = false;

        Charset charset = Charset.forName("ascii");

        FastIO io = local ? new FastIO(new FileInputStream("D:\\DATABASE\\TESTCASE\\Code.in"), System.out, charset) : new FastIO(System.in, System.out, charset);
        Task task = new Task(io, new Debug(local));

        if (async) {
            Thread t = new Thread(null, task, "dalt", 1 << 27);
            t.setPriority(Thread.MAX_PRIORITY);
            t.start();
            t.join();
        } else {
            task.run();
        }

        if (local) {
            io.cache.append("\n\n--memory -- \n" + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20) + "M");
        }

        io.flush();
    }

    public static class Task implements Runnable {
        final FastIO io;
        final Debug debug;
        int inf = (int) 1e8;
        int mod = 998244353;
        int[][][] mem;
        boolean[][][] visit;
        int l1;
        int l2;
        int l3;
        int n;
        int k;
        int time;

        public Task(FastIO io, Debug debug) {
            this.io = io;
            this.debug = debug;
        }

        @Override
        public void run() {
            solve();
        }

        public void solve() {
            n = io.readInt();
            k = io.readInt();
            int l = io.readInt();
            mem = new int[2][n + 1][n + 1];
            visit = new boolean[2][n + 1][n + 1];
            int meetCount = find(n, n, 1);

            int factorial = 1;
            for (int i = 2, until = 2 * n + 1; i <= until; i++) {
                factorial = mul(factorial, i);
            }
            int total = mul(factorial, Mathematics.inverse(Mathematics.pow(2, n, mod), mod));
            int probability = mul(meetCount, Mathematics.inverse(total, mod));
            int expectLength = mul(l, probability);
            io.cache.append(expectLength);
        }

        public int add(int a, int b) {
            return (a + b) % mod;
        }

        public int sub(int a, int b) {
            if (a >= b) {
                return a - b;
            }
            return a - b + mod;
        }

        public int mul(int a, int b) {
            return (int) (((long) a * b) % mod);
        }

        public int find(int i, int j, int x) {
            time++;
            if (i < 0 || i > n || j < 0 || j > n) {
                return 0;
            }
            if (i == 0 && j == 0 && x == 0) {
                return 1;
            }
            if (visit[x][i][j]) {
                return mem[x][i][j];
            }
            visit[x][i][j] = true;
            mem[x][i][j] = 0;
            if (i < j) {
                return 0;
            }
            if (x == 1) {
                mem[x][i][j] = add(mem[x][i][j], mul(find(i, j, 0), (i - j >= k ? 1 : 0)));
            }
            mem[x][i][j] = add(mem[x][i][j], mul((n - i + 1), find(i - 1, j, x)));
            mem[x][i][j] = add(mem[x][i][j], mul((i - j + 1), find(i, j - 1, x)));
            return mem[x][i][j];
        }
    }

    public static class Mathematics {

        public static int ceilPowerOf2(int x) {
            return 32 - Integer.numberOfLeadingZeros(x - 1);
        }

        public static int floorPowerOf2(int x) {
            return 31 - Integer.numberOfLeadingZeros(x);
        }

        public static long modmul(long a, long b, long mod) {
            return b == 0 ? 0 : ((modmul(a, b >> 1, mod) << 1) % mod + a * (b & 1)) % mod;
        }

        /**
         * Get the greatest common divisor of a and b
         */
        public static int gcd(int a, int b) {
            return a >= b ? gcd0(a, b) : gcd0(b, a);
        }

        private static int gcd0(int a, int b) {
            return b == 0 ? a : gcd0(b, a % b);
        }

        public static int extgcd(int a, int b, int[] coe) {
            if (a >= b) {
                return extgcd0(a, b, coe);
            } else {
                int g = extgcd0(b, a, coe);
                int tmp = coe[0];
                coe[0] = coe[1];
                coe[1] = tmp;
                return g;
            }
        }

        private static int extgcd0(int a, int b, int[] coe) {
            if (b == 0) {
                coe[0] = 1;
                coe[1] = 0;
                return a;
            }
            int g = extgcd0(b, a % b, coe);
            int n = coe[0];
            int m = coe[1];
            coe[0] = m;
            coe[1] = n - m * (a / b);
            return g;
        }

        /**
         * Get the greatest common divisor of a and b
         */
        public static long gcd(long a, long b) {
            return a >= b ? gcd0(a, b) : gcd0(b, a);
        }

        private static long gcd0(long a, long b) {
            return b == 0 ? a : gcd0(b, a % b);
        }

        public static long extgcd(long a, long b, long[] coe) {
            if (a >= b) {
                return extgcd0(a, b, coe);
            } else {
                long g = extgcd0(b, a, coe);
                long tmp = coe[0];
                coe[0] = coe[1];
                coe[1] = tmp;
                return g;
            }
        }

        private static long extgcd0(long a, long b, long[] coe) {
            if (b == 0) {
                coe[0] = 1;
                coe[1] = 0;
                return a;
            }
            long g = extgcd0(b, a % b, coe);
            long n = coe[0];
            long m = coe[1];
            coe[0] = m;
            coe[1] = n - m * (a / b);
            return g;
        }

        /**
         * Get y where x * y = 1 (% mod)
         */
        public static int inverse(int x, int mod) {
            return pow(x, mod - 2, mod);
        }

        /**
         * Get x^n(% mod)
         */
        public static int pow(int x, int n, int mod) {
            n = mod(n, mod - 1);
            x = mod(x, mod);
            int bit = 31 - Integer.numberOfLeadingZeros(n);
            long product = 1;
            for (; bit >= 0; bit--) {
                product = product * product % mod;
                if (((1 << bit) & n) != 0) {
                    product = product * x % mod;
                }
            }
            return (int) product;
        }

        public static long longpow(long x, long n, long mod) {
            if (n == 0) {
                return 1;
            }
            long prod = longpow(x, n >> 1, mod);
            prod = modmul(prod, prod, mod);
            if ((n & 1) == 1) {
                prod = modmul(prod, x, mod);
            }
            return prod;
        }

        /**
         * Get x % mod
         */
        public static int mod(int x, int mod) {
            return x >= 0 ? x % mod : (((x % mod) + mod) % mod);
        }

        /**
         * Get n!/(n-m)!
         */
        public static long permute(int n, int m) {
            return m == 0 ? 1 : n * permute(n - 1, m - 1);
        }

        /**
         * Put all primes less or equal to limit into primes after offset
         */
        public static int eulerSieve(int limit, int[] primes, int offset) {
            boolean[] isComp = new boolean[limit + 1];
            int wpos = offset;
            for (int i = 2; i <= limit; i++) {
                if (!isComp[i]) {
                    primes[wpos++] = i;
                }
                for (int j = offset, until = limit / i; j < wpos && primes[j] <= until; j++) {
                    int pi = primes[j] * i;
                    isComp[pi] = true;
                    if (i % primes[j] == 0) {
                        break;
                    }
                }
            }
            return wpos - offset;
        }

        /**
         * Round x into integer
         */
        public static int intRound(double x) {
            if (x < 0) {
                return -(int) (-x + 0.5);
            }
            return (int) (x + 0.5);
        }

        /**
         * Round x into long
         */
        public static long longRound(double x) {
            if (x < 0) {
                return -(long) (-x + 0.5);
            }
            return (long) (x + 0.5);
        }
    }

    public static class FastIO {
        public final StringBuilder cache = new StringBuilder();
        private final InputStream is;
        private final OutputStream os;
        private final Charset charset;
        private StringBuilder defaultStringBuf = new StringBuilder(1 << 8);
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastIO(InputStream is, OutputStream os, Charset charset) {
            this.is = is;
            this.os = os;
            this.charset = charset;
        }

        public FastIO(InputStream is, OutputStream os) {
            this(is, os, Charset.forName("ascii"));
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public long readLong() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            long val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public double readDouble() {
            boolean sign = true;
            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+';
                next = read();
            }

            long val = 0;
            while (next >= '0' && next <= '9') {
                val = val * 10 + next - '0';
                next = read();
            }
            if (next != '.') {
                return sign ? val : -val;
            }
            next = read();
            long radix = 1;
            long point = 0;
            while (next >= '0' && next <= '9') {
                point = point * 10 + next - '0';
                radix = radix * 10;
                next = read();
            }
            double result = val + (double) point / radix;
            return sign ? result : -result;
        }

        public String readString(StringBuilder builder) {
            skipBlank();

            while (next > 32) {
                builder.append((char) next);
                next = read();
            }

            return builder.toString();
        }

        public String readString() {
            defaultStringBuf.setLength(0);
            return readString(defaultStringBuf);
        }

        public int readLine(char[] data, int offset) {
            int originalOffset = offset;
            while (next != -1 && next != '\n') {
                data[offset++] = (char) next;
                next = read();
            }
            return offset - originalOffset;
        }

        public int readString(char[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (char) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public int readString(byte[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (byte) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public char readChar() {
            skipBlank();
            char c = (char) next;
            next = read();
            return c;
        }

        public void flush() {
            try {
                os.write(cache.toString().getBytes(charset));
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public boolean hasMore() {
            skipBlank();
            return next != -1;
        }
    }

    public static class Debug {
        private boolean allowDebug;

        public Debug(boolean allowDebug) {
            this.allowDebug = allowDebug;
        }

        public void assertTrue(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (!flag) {
                fail();
            }
        }

        public void fail() {
            throw new RuntimeException();
        }

        public void assertFalse(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (flag) {
                fail();
            }
        }

        private void outputName(String name) {
            System.out.print(name + " = ");
        }

        public void debug(String name, int x) {
            if (!allowDebug) {
                return;
            }

            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, long x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, double x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, int[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, long[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, double[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, Object x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, Object... x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.deepToString(x));
        }
    }
}


//package Contest551;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;

public class mainF {
    public static Scanner enter = new Scanner(System.in);
    public static PrintWriter out = new PrintWriter(System.out);
    public static long mod=998244353;
    public static long cnk[][]=new long[(int)2e3+2][(int)2e3+2];
    public static long fact[]=new long[2*(int)2e3+2];
    public static long reverse[]=new long[2*(int)2e3+2];
    public static long deg_2[]=new long[(int)2e3+2];
    public static void main(String[] args) {
        long t=System.currentTimeMillis();
        cnk[0][0]=1;
        for (int i = 1; i <cnk.length ; i++) {
            cnk[0][i]=1;
            for (int j = 1; j <=i ; j++) {
                cnk[j][i]=cnk[j-1][i-1]+cnk[j][i-1];
                cnk[j][i]%=mod;
            }
        }
        fact[0]=1;
        deg_2[0]=1;
        for (int i = 1; i <fact.length ; i++) {
            fact[i]=fact[i-1]*i;
            fact[i]%=mod;
        }
        for (int i = 1; i <deg_2.length ; i++) {
            deg_2[i]=deg_2[i-1]*2;
            deg_2[i]%=mod;
        }
        reverse[1]=1;
        for (int i = 3; i <reverse.length ; i+=2) {
            reverse[i]=bin_pow(fact[i],mod-2,mod);
        }
       /* System.out.println(Arrays.toString(reverse));
        System.out.println(fact[5]);
        System.out.println(reverse[5]);*/
        int n=enter.nextInt();
        int k=enter.nextInt();
        long l=enter.nextInt();
        l%=mod;
        long ans=0;
        for (int i = k; i <=n ; i++) {
            long tmp=0;
            for (int s = 0,c=1; s <=n-i ; s++,c*=-1) {
                long a=1;
                a*=cnk[s][n-i]*deg_2[s];
                a%=mod;
                a*=fact[s+i];
                a%=mod;
                a*=fact[s+i];
                a%=mod;
                a*=reverse[2*(s+i)+1];
                a%=mod;
                tmp+=a*c;
                tmp%=mod;
               // System.out.println(reverse[2*(s+i)+1]);
            }
            //System.out.println(tmp);
            /*ans+=cnk[i][n]*deg_2[i]*tmp;
            ans%=mod;*/
            long  b=1;
            b*=tmp*deg_2[i];
            b%=mod;
            //System.out.println(b);
            b*=cnk[i][n];
            b%=mod;
            ans+=b;
            ans%=mod;
        }
        ans*=l;
        ans%=mod;
        System.out.println((ans<0)? (ans+mod) : ans);

      //  System.out.println(System.currentTimeMillis()-t);

    }
    public static long bin_pow(long a,long b, long mod){//a^b %mod
        long ans=1;
        while(b!=0){
            if((b&1)==1) ans*=a;
            a*=a;
            ans%=mod;
            a%=mod;
            b>>=1;
        }
        return ans;
    }
}


//Created by Aminul on 11/17/2020.

import java.io.*;
import java.util.*;

import static java.lang.Math.*;

public class CF1447F1 {
    public static void main(String[] args) throws Exception {
        Scanner in = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        int n = in.nextInt();
        int[] arr = new int[n + 1];
        int[] freq = new int[101];
        int mostFreq = 0;
        for (int i = 1; i <= n; i++) {
            arr[i] = in.nextInt();
            freq[arr[i]]++;
            if (freq[arr[i]] > freq[mostFreq]) {
                mostFreq = arr[i];
            }
        }

        int res = 0;
        for (int i = 1; i <= 100; i++) {
            if (i != mostFreq) {
                int tmp = maxSumArrayWithZeroSum(n, mostFreq, i, arr);
                res = max(res, tmp);
            }
        }

        pw.println(res);
        pw.close();
    }

    static int maxSumArrayWithZeroSum(int n, int x, int y, int[] arr) {
        int offset = n + 5;
        int[] idx = new int[offset + offset + 10];
        int invalid = -n - n - n;
        Arrays.fill(idx, invalid);
        int sum = 0, res = 0;
        idx[offset + sum] = 0;
        for (int i = 1; i <= n; i++) {
            if (arr[i] == x) sum++;
            else if (arr[i] == y) sum--;
            if (idx[offset + sum] != invalid) res = max(res, i - idx[offset + sum]);
            else idx[offset + sum] = i;
        }
        return res;
    }

    static void debug(Object... obj) {
        System.err.println(Arrays.deepToString(obj));
    }
}