#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PP;
#define MOD 1000000007
//#define MOD 998244353
#define INF 2305843009213693951
//#define INF 810114514
#define PI 3.141592653589
#define setdouble setprecision
#define REP(i,n) for(ll i=0;i<(n);++i)
#define OREP(i,n) for(ll i=1;i<=(n);++i)
#define RREP(i,n) for(ll i=(n)-1;i>=0;--i)
#define all1(i) begin(i),end(i)
#define GOODBYE do { cout << "-1" << endl; return 0; } while (false)
#define MM <<" "<<
#define Endl endl
#define debug true
#define debug2 false

class unionfind{
    /*
    Copyright (c) 2020 0214sh7
    https://github.com/0214sh7/library/
    */
    private:
    std::vector<int> UF,rank;
    public:
    
    void init(int N){
        UF.clear();
        rank.clear();
        for(int i=0;i<N;i++){
            UF.push_back(i);
            rank.push_back(0);
        }
    }
    
    int root(int k){
        if(UF[k]==k){
            return k;
        }else{
            UF[k]=root(UF[k]);
            return UF[k];
        }
    }
    
    bool same(int p,int q){
        return root(p)==root(q);
    }
    
    void unite(int P,int Q){
        int p=root(P);
        int q=root(Q);
        if(p==q)return;
        if(rank[p]<rank[q])std::swap(p,q);
        UF[q]=p;
        if(rank[p]==rank[q])rank[p]++;
    }
    
};


int main(void){
    ll H,W;
    vector<string> S;
    cin >> H >> W;
    REP(i,H){
        string s;
        cin >> s;
        S.push_back(s);
    }
    
    if(H<=2 || W<=2){
        cout << 0 << endl;
        return 0;
    }
    
    unionfind UF;
    UF.init(H+W-3);
    
    //0:外周
    //1~H-2:横線
    //H-1~H+W-4:縦線
    
    for(ll i=1;i<H-1;i++){
        if(S[i][0]=='#' || S[i][W-1]=='#'){
            UF.unite(0,i);
        }
    }
    
    for(ll j=1;j<W-1;j++){
        if(S[0][j]=='#' || S[H-1][j]=='#'){
            UF.unite(0,H-2+j);
        }
    }
    
    for(ll i=1;i<H-1;i++){
        for(ll j=1;j<W-1;j++){
            if(S[i][j]=='#'){
                UF.unite(i,H-2+j);
            }
        }
    }
    
    set<ll> Y,X;
    Y.insert(UF.root(0));
    X.insert(UF.root(0));
    for(ll i=1;i<H-1;i++){
        Y.insert(UF.root(i));
    }
    for(ll i=H-1;i<H+W-3;i++){
        X.insert(UF.root(i));
    }
    
    ll R=Y.size()-1,C=X.size()-1;
    
    //cout << R MM C << endl;
    cout << min(R,C) << endl;
    
    return 0;
}
#include <iostream>
#include <iomanip>
#include <vector>
#include <set>
#include <string>
#include <queue>
#include <algorithm>
#include <map>
#include <cmath>
#include <numeric>
#include <list>
#include <stack>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <tuple>
#include <deque>
#include <complex>
#include <bitset>
#include <functional>
#include <cassert>
//#include <atcoder/all>

using namespace std;
//using namespace atcoder;

using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using pll = pair<ll, ll>;
using vpll = vector<pll>;
using ld = long double;
using vld = vector<ld>;
using vb = vector<bool>;

#define rep(i, n) for (ll i = 0; i < (n); i++)
#ifdef LOCAL
#define dbg(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl
#else
#define dbg(x) true
#endif

template <class T> void chmin(T& a, T b) { a = min(a, b);}
template <class T> void chmax(T& a, T b) { a = max(a, b);}
template <class T> ostream& operator<<(ostream& s, const vector<T>& a) { for(auto i : a) s << i << ' '; return s; }

constexpr ll INFL = 1LL << 60;
constexpr ld EPS = 1e-12;
ld PI = acos(-1.0);

struct mint {
    static const long long mod = 998244353;
    long long x;
    mint(long long x = 0) : x((x % mod + mod) % mod) {}
    mint operator-() const { return mint(-x);}
    mint& operator+=(const mint& a) {if ((x += a.x) >= mod) x -= mod; return *this;}
    mint& operator-=(const mint& a) {if ((x += mod - a.x) >= mod) x -= mod; return *this;}
    mint& operator*=(const mint& a) {(x *= a.x) %= mod; return *this;}

    friend const mint operator+(const mint& a, const mint& b) { mint ret = a; return ret += b; }
    friend const mint operator-(const mint& a, const mint& b) { mint ret = a; return ret -= b; }
    friend const mint operator*(const mint& a, const mint& b) { mint ret = a; return ret *= b; }
    friend ostream& operator<<(ostream& s, const mint& a) { return s << a.x; }

    mint pow(long long t) const {
        if (!t) return 1;
        mint a = pow(t >> 1);
        a *= a;
        if (t & 1) a *= *this;
        return a;
    }

    // for prime mod
    mint inv() const { return pow(mod - 2);}
    mint& operator/=(const mint a) { return (*this) *= a.inv();}
    friend const mint operator/(const mint& a, const mint& b) { mint ret = a; return ret /= b; }
};

void solve() {
    ll h, w, k;
    cin >> h >> w >> k;
    vector<string> s(h, string(w, '.'));
    rep(i, k) {
        ll h_, w_;
        char c_;
        cin >> h_ >> w_ >> c_;
        s[h_-1][w_-1] = c_;
    }
    /*
    rep(i, h) {
        rep(j, w) cout << s[i][j] << ' ';
        cout << endl;
    }
    */
    using vm = vector<mint>;
    vector<vm> dp(h, vm(w));
    dp[0][0] = mint(3).pow(h*w-k);
    mint inv3 = mint(3).inv();
    rep(i, h) rep(j, w) {
        if(i > 0) {
            if(s[i-1][j] == '.') dp[i][j] += dp[i-1][j] * 2 * inv3;
            else if(s[i-1][j] == 'D' || s[i-1][j] == 'X') dp[i][j] += dp[i-1][j];
        }
        if(j > 0) {
            if(s[i][j-1] == '.') dp[i][j] += dp[i][j-1] * 2 * inv3;
            else if(s[i][j-1] == 'R' || s[i][j-1] == 'X') dp[i][j] += dp[i][j-1];
        }
    }
    cout << dp[h-1][w-1] << endl;
    /*
    rep(i, h) {
        rep(j, w) cout << dp[i][j] << ' ';
        cout << endl;
    }
    */
    return;
}

int main() {
    std::cin.tie(nullptr);
    std::ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    solve();
}