#include <bits/stdc++.h>
#define REP(i, n) for(int i=0; i < (int)(n); i++)
using namespace std;

typedef long long ll;
// #define DEBUG

int H, W, K;
vector<vector<int>> original;
vector<vector<int>> board;

struct EraseResult{
    set<int> erased;
    ll score;
};

void drop(set<int>& erased){
    #ifdef DEBUG
    printf("drop\n");
    #endif
    for(auto col: erased){
        // col列目を落とす
        while(true){
            int changed = false;
            for(int bottom=H-2; bottom >= 0; bottom--){
                if(board[bottom][col] != 0 && board[bottom+1][col] == 0){
                    board[bottom+1][col] = board[bottom][col];
                    board[bottom][col] = 0;
                    changed = true;
                }
            }

            if(changed == false){
                break;
            }
        }
        

        // int seeker = H - 1;
        // // bottomは下から順につめていく。seekerは非空ブロックをさがしにいく.
        // for(int bottom = H-1; bottom >= 0; bottom--){
        //     // seekerをうえにあげてブロックをさがす
        //     while(seeker >= 0 && board[seeker][col] == 0){
        //         seeker--;
        //     }

        //     if(seeker < 0){
        //         // みつからなかったその列はおわり   
        //         break;
        //     }

        //     // ブロックをみつけたらそれはけしてbottomのところにうつす
        //     board[bottom][col] = board[seeker][col];
        //     board[seeker][col] = 0;
        // }
    }
}

EraseResult tryEraseRow(int i, int j){
    if(board[i][j] == 0){
        return EraseResult{set<int>(), 0};
    }
    #ifdef DEBUG
    printf("tryEraseRow(%d, %d) %d\n", i, j, board[i][j]);
    #endif

    int left = j;
    while(left - 1 >= 0 && board[i][left-1] == board[i][j]){
        left--;
    }

    int right = j;
    while(right + 1 < W && board[i][right+1] == board[i][j]){
        right++;
    }

    int len = right - left + 1;
    if(len >= K){
        ll res = board[i][j]*len;
        // けす
        set<int> erased;
        for(int ind=left; ind <= right; ind++){
            board[i][ind] = 0;
            erased.insert(ind);
        }
        #ifdef DEBUG
        printf("Earned %d\n", res);
        #endif
        return EraseResult{erased, res};

    }else{
        // けせない
        return EraseResult{set<int>(), 0};
    }
}

EraseResult eraseAndEarn(set<int>& dropped){
    #ifdef DEBUG
    printf("eraseAndEarn\n");
    #endif
    ll score = 0;
    set<int> erased;
    for(auto col: dropped){
        for(int i=0; i < H; i++){
            auto res = tryEraseRow(i, col);
            if(res.score > 0){
                // けせて
                score += res.score;
                for(auto iter: res.erased){
                    erased.insert(iter);
                }
            }
        }
    }

    return EraseResult{erased, score};
}




ll simulate(int i, int j){
    // ボードをコピー
    board = original;

    // 穴をあける
    board[i][j] = 0;

    // 効率化のためにどの列を落としたか/けしたかをおぼえておく
    set<int> erased;
    erased.insert(j);

    // 落とす→けして点を得るを繰替えす。
    ll res = 0;
    ll mag = 1;  // 点の倍率
    while(true){
        drop(erased);

        // 前回けしたところしか落ちてないのでそこだけしらべれば十分
        auto erase_res = eraseAndEarn(erased);
        ll local_score = erase_res.score;
        if(local_score == 0){
            break;
        }
        erased = erase_res.erased;
        res += local_score*mag;

        mag *= 2;
    }

    return res;
}

int main(){
    cin >> H >> W >> K;

    original = vector<vector<int>>(H, vector<int>(W, 0));
    for(int i=0; i < H; i++){
        for(int j=0; j < W; j++){
            while(true){
                char temp;
                cin >> temp;
                if('0' <= temp && temp <= '9'){
                    original[i][j] = temp - '0';
                    break;
                }else{
                    continue;
                }
            }
        }
    }

    ll res = 0;
    for(int i=0; i < H; i++){
        for(int j=0; j < W; j++){
            res = max(res, simulate(i, j));
        }
    }
    
    cout << res << endl;


    return 0;

}

Measured memory_bytes: 256