Problem:
Problem B:
Red and Black
There is a rectangular room, covered with square tiles. Each tile is
colored either red or black. A man is standing on a black tile.
From a tile, he can move to one of four adjacent tiles. But he can't 
move on red tiles, he can move only on black tiles.
Write a program to count the number of black tiles which he can reach 
by repeating the moves described above.
Input
The input consists of multiple data sets.
 A data set starts with a line containing two positive integers
W
and
H
;
W
and
H
are the numbers of tiles in the
x
-
 and
y
- directions, respectively.
W
and
H
are 
not more than 20.
There are
H
more lines in the data set, each of which
includes
W
characters. Each character represents the color of a
tile as follows.
'.' - a black tile
'#' - a red tile
'@' - a man on a black tile(appears exactly once in a data set)
The end of the input is indicated by a line consisting of two zeros.
Output
For each data set, your program 
should output a line which contains the number of 
tiles he can reach from the initial tile (including itself).
Sample Input
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0
Output for the Sample Input
45
59
6
13

Submitted solutions:

code_snippet: //会う時と+1のとき

//いくつもとけるように
//countの初期値直した　テストケース2つokおそらくいける　タリーズでwifi繋がらずまだ
//69のaojテストケースでanswer45なのに1
//隣接リストを用意→＠からbfs　-1でなかった点を数え上げる
#include <iostream>
#include <queue>
using namespace std;

int bfs(int src, int n, int G[410][410]){ //srcは始点のk　nはw*h　Gはおっきな隣接リスト
    queue<int> Q;
    Q.push(src);
    int D[n+10];
    for (int i=0; i<n+10; ++i){
        D[i] = -1; //他はinf
    }
    D[src] = 0; //スタートは0
    while (! Q.empty()){
        int cur = Q.front();
        Q.pop(); //先頭取り出す
        for (int dst=0; dst<n+1; ++dst){ //全頂点
            if ((G[cur][dst] == 1) && (D[dst] == -1)){ //辺があってまだinfなら
                D[dst] = D[cur] + 1; //D更新
                Q.push(dst); //その点を新たな起点に
            }
        }
    }
    //Dから-1でないところを全部出す
    int count = 0; //スタート含む 0に戻した
    for (int t=0; t<n+10; ++t){
        if (D[t] > -1) {
            count += 1;
            //cout << "passable t = " << t << endl;
        }
    }
    return count;
}

bool valid(int x, int y, int w, int h, int R[20][20]){
    return (0 <= x) && (x < w) && (0 <= y) && (y < h) && (R[y][x] > 0);
//     return x が [0,W] の範囲 2
// && y が [0,H] の範囲 3
// && (x,y) が壁でない; 
}


const int dx[4]={1,0,-1,0}, dy[4]={0,-1,0,1};
int main(){
    while (true) {
        int w, h;
        int rs, cs;
        //cout << "hi." << endl;
        cin >> w >> h;
        if (w==0 && h==0) break;
        else{
            //cout << w << h << endl;
            int R[20][20];
            //Rは入力のコピー　記号を数字にしただけ
            for (int i=0; i<h; ++i){
                string li;
                cin >> li; //li = ...#..
                //cout << li << endl;
                for (int j=0; j<w; ++j){
                    if (li[j] == '.') R[i][j] = 1;
                    if (li[j] == '#') {
                        R[i][j] = 0;
                        //cout << i << j << endl;
                    }
                    if (li[j] == '@') {
                        R[i][j] = 1;
                        rs = i;
                        cs = j;
                    } //スタートだったら
                }
            }
            // for (int r=0; r<h; ++r){ Rはできてる！！
            //     for (int c=0; c<w; ++c){
            //         cout << R[r][c];
            //     }
            //     cout << endl;
            // }
            //隣接リストを作る　一辺w*h　r行c列の要素は　左から w*r+c番目(0開始)
            int n = w*h;
            int G[410][410] = {0}; //Gを隣接リストに！
            //全頂点に対して隣の4つ調べる　validなら1に
            for (int r=0; r<h; ++r){ //多分ここ　斜め下が1だったり真下なのに0だった
                for (int c=0; c<w; ++c){
                    int k = w*r + c;
                    for (int i=0; i<4; ++i){ //隣4つ調べる
                        int r_ = r + dy[i]; int c_ = c + dx[i];
                        int k_ = w*r_ + c_;
                        if (valid(c_, r_,  w, h, R)) G[k][k_] = 1; //多分ここ→よさそう
                    }
                }
            }
            // for (int s=0; s<n; ++s){ //テスト
            //     for (int t=0; t<n; ++t){
            //         cout << G[s][t];
            //     }
            //     cout << endl;
            // }
            //以上でG完成
            int src = w*rs + cs;
            cout << bfs(src, n, G) << endl;
        }
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3704
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;

void dfs(vector< vector<int> > &mat, int cur, vector<bool> &visited, int &count) {
    visited[cur] = true;
    count++;
    for (int dst = 0; dst < mat[cur].size(); dst++) {
        if (mat[cur][dst] && !visited[dst]) {
            dfs(mat, dst, visited, count);
        }
    }
}

int main() {
    int W, H;
    while (true) {
        cin >> W >> H;
        if (W == 0 && H == 0) break;
        vector< vector<char> > map(H, vector<char>(W, 0));
        int at;
        string buf;
        for (int i = 0; i < H; i++) {
            cin >> buf;
            for (int j = 0; j < W; j++) {
                char b = buf[j];
                if (b == '@') at = i * W + j;
                map[i][j] = buf[j];
            }
        }
        auto valid = [&](int x, int y) {
            return 0 <= x && x < W && 0 <= y && y < H && map[y][x] != '#';
        };
        vector< vector<int> > adjMatrix(H * W + W, vector<int>(H * W + W, 0));
        const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
        for (int y = 0; y < H; y++) {
            for (int x = 0; x < W; x++) {
                if (!valid(x, y)) continue;
                for (int i = 0; i < 4; i++) {
                    int nx = x + dx[i], ny = y + dy[i];
                    if (valid(nx, ny)) adjMatrix[y * W + x][ny * W + nx] = 1;
                }
            }
        }
        vector<bool> visited(H * W + W, false);
        int count = 0;
        dfs(adjMatrix, at, visited, count);
        cout << count << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3992
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <algorithm>
using namespace std;

vector<int> bfs(vector< vector<int> > mat, int src) {
    vector<int> D(mat.size(), -1);
    queue<int> Q;
    Q.push(src);
    D[src] = 0;
    while (!Q.empty()) {
        int cur = Q.front();
        Q.pop();
        for (int dst = 0; dst < mat[cur].size(); dst++) {
            if (mat[cur][dst] && D[dst] == -1) {
                D[dst] = D[cur] + 1;
                Q.push(dst);
            }
        }
    }   
    return D;
}

int main() {
    int W, H;
    while (true) {
        cin >> W >> H;
        if (W == 0 && H == 0) break;
        vector< vector<char> > map(H, vector<char>(W, 0));
        int at;
        string buf;
        for (int i = 0; i < H; i++) {
            cin >> buf;
            for (int j = 0; j < W; j++) {
                char b = buf[j];
                if (b == '@') at = i * W + j;
                map[i][j] = buf[j];
            }
        }
        auto valid = [&](int x, int y) {
            return 0 <= x && x < W && 0 <= y && y < H && map[y][x] != '#';
        };
        vector< vector<int> > adjMatrix(H * W + W, vector<int>(H * W + W, 0));
        const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
        for (int y = 0; y < H; y++) {
            for (int x = 0; x < W; x++) {
                if (!valid(x, y)) continue;
                for (int i = 0; i < 4; i++) {
                    int nx = x + dx[i], ny = y + dy[i];
                    if (valid(nx, ny)) adjMatrix[y * W + x][ny * W + nx] = 1;
                }
            }
        }
        vector<int> res = bfs(adjMatrix, at);
        cout << count_if(res.begin(), res.end(), [](int x) { return x != -1; }) << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 4840
final_rank: 7

code_snippet: #include<iostream>
#include<vector>
#include<queue>
using namespace std;
int c=0;
int dx[4]={1, 0, -1, 0};
int dy[4]={0, 1, 0, -1};
vector<vector<bool> > is_visited(25,vector<bool>(25));

void initialize_is_visited(){
    for(int i=0;i<25;i++){
        for(int j=0;j<25;j++){
            is_visited[j][i]=false;
        }
    }
}

bool is_movable(int x,int y,vector<vector<bool> > edge){//trueで壁でも範囲外でもない
    if(x>=0&&y>=0&&x<edge.size()&&y<edge[0].size()){
        if(edge[x][y]) return true;
    }
    return false;
}

void dfs(int x,int y,vector<vector<bool> > edge){
    is_visited[x][y]=true;//trueで訪問済
    /*for(int i=0;i<is_visited[0].size();i++){
        for(int j=0;j<is_visited.size();j++){
            cout << is_visited[j][i] << " ";
        }
        cout << endl;
    }*/
    c++;
    for(int i=0;i<4;i++){
        //cout << "visiting (" << x << "," << y << ")" << endl;
        if(is_movable(x+dx[i],y+dy[i],edge)){
            //cout << "will go to " << x+dx[i] << "," << y+dy[i] << "and" <<is_visited[x+dx[i]][y+dy[i]] << endl;
            if(is_visited[x+dx[i]][y+dy[i]]==false){
            dfs(x+dx[i],y+dy[i],edge);
            }
        }
    }
}

int main(){

    queue<int> Q;
    int w,h;

    while(cin >> w >> h){
        if(w==0&&h==0) break;
        vector<vector<bool> > edge(w, vector<bool>(h));
        int x,y;
        for(int i=0;i<h;i++){
            for(int j=0;j<w;j++){
                char b;
                cin >> b;
                if(b=='.') edge[j][i]=true;
                else if(b=='#') edge[j][i]=false;
                else{
                    edge[j][i]=false;
                    x=j;
                    y=i;
                }
            }
        }
        dfs(x,y,edge);
        Q.push(c);
        c=0;
        initialize_is_visited();
    }

    while(!Q.empty()){
        int n;
        n=Q.front();
        Q.pop();
        cout << n << endl;
    }
}
accuracy: 1
time_ms: 50
memory_kb: 3636
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define all(v) v.begin(), v.end()
#define rep(i, begin, end) for(auto i = (begin); i < (end); i++)
#define rrep(i, end, begin) for(auto i = (end) - 1; i >= (begin); i--)
template<class T> inline bool chmin(T& a, T b){ if (a > b){ a = b; return true; } return false; }
template<class T> inline bool chmax(T& a, T b){ if (a < b){ a = b; return true; } return false; }
template<class T> inline T roundup(T a, T b){ return (a + b - 1) / b; }
constexpr int dy[] = {0, 1, 0, -1, 1, 1, -1, -1, 0};
constexpr int dx[] = {1, 0, -1, 0, 1, -1, 1, -1, 0};
using ll = long long;
constexpr ll INF = 1e9;
using Graph = vector<vector<int>>;

void solve(int w, int h){
    queue<pair<int, int>> q;
    vector seen(h, vector(w, false));
    
    vector t(h, vector(w, '.'));
    rep(i, 0, h) rep(j, 0, w){
        cin >> t[i][j];
        if(t[i][j] == '@'){
            q.emplace(i, j), seen[i][j] = true;
            t[i][j] = '.';
        }
    }
    
    auto is_valid_move = [&](int yp, int xp){
        if(!(0 <= yp && yp < h && 0 <= xp && xp < w)) return false;
        return t[yp][xp] == '.';
    };
    
    while(!q.empty()){
        auto [y, x] = q.front(); q.pop();
        seen[y][x] = true;
        rep(i, 0, 4){
            int yp = y + dy[i], xp = x + dx[i];
            if(!is_valid_move(yp, xp) || seen[yp][xp]) continue;
            q.emplace(yp, xp);
        }
    }
    
    int ans = 0;
    rep(i, 0, h) rep(j, 0, w) ans += seen[i][j];
    cout << ans << endl;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    
    int w, h;
    while(true){
        cin >> w >> h;
        if(w == 0 && h == 0) return 0;
        solve(w, h);
    }
}
accuracy: 1
time_ms: 80
memory_kb: 6208
final_rank: 9

code_snippet: #include<iostream>
#include<cmath>
#include<deque>
#include<queue>
#include <map>
//#include <unordered_map>
#include <vector>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <set>
using namespace std;
//using ll=long long;
//using mint = modint998244353;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rep2(i, n) for (int i = 1; i <= (int)(n); i++)

using namespace std;

#if 0
先日の深さ優先探索のものを改造するだけだったので10分程度できた。ただ、複数のデータセットに対応するために、いちいち初期化するのを忘れた。
#endif

vector<vector<int> > g(101);
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

void dfs(int x,int y,int &ans,map<pair<int,int>,int> &mp,map<pair<int,int>,char> &mapp){
    mp[{x,y}] = 1;
    ans++;
    for(int i=0;i<4;i++){
        if(mp[{x+dx[i],y+dy[i]}]==0 && mapp[{x+dx[i],y+dy[i]}]=='.'){//訪れていないかつ到達可能
            //t++;
            dfs(x+dx[i],y+dy[i],ans,mp,mapp);
        }
    }
}

int main(){
    vector<int> answers;
    while(true){
        int answer = 0;
        map<pair<int,int>,char> mapp;//記号を管理
        int w,h;cin>>w>>h;
        if(w==0&&h==0) break;
        pair<int,int> start;
        rep(i,h){
            string tmp;cin>>tmp;
            rep(j,w){
                mapp[{i,j}] = tmp[j];
                if(mapp[{i,j}]=='@'){
                    start = {i,j};
                }
            }
        }
        map<pair<int,int>,int> mp;//訪れたかを管理する。
        dfs(start.first,start.second,answer,mp,mapp);
        answers.push_back(answer);
    }   
    for(auto e:answers){
        cout << e << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3452
final_rank: 2

code_snippet: #include<iostream>
#include<cmath>
#include<deque>
#include<queue>
#include <map>
//#include <unordered_map>
#include <vector>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <set>
using namespace std;
//using ll=long long;
//using mint = modint998244353;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rep2(i, n) for (int i = 1; i <= (int)(n); i++)

using namespace std;

#if 0
#endif

vector<vector<int> > g(101);
//int seen[21][21];
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int main(){
    vector<int> answers;
    while(true){
        int answer = 1;
        map<pair<int,int>,char> mapp;//記号を管理
        int w,h;cin>>w>>h;
        if(w==0&&h==0) break;
        pair<int,int> start;
        rep(i,h){
            string tmp;cin>>tmp;
            rep(j,w){
                mapp[{i,j}] = tmp[j];
                if(mapp[{i,j}]=='@') start = {i,j};
            }
        }
        queue<pair<int,int> > q;
        map<pair<int,int>,int> mp;//訪れたかを管理する。
        q.push(start);
        mp[start] = 1;
        while(!q.empty()){
            pair<int,int> d = q.front();
            q.pop();
            for(int i=0;i<4;i++){//上下左右の4方向
                pair<int,int> nextd;
                nextd = {d.first+dy[i],d.second+dx[i]};
                if(mp[nextd]==0 && mapp[nextd]=='.'){//訪れていないかつ到達可能
                    q.push(nextd);
                    mp[nextd] = 1;//訪れたことにする。
                    answer++;
                }
            }
        }
        answers.push_back(answer);
    }   
    for(auto e:answers){
        cout << e << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3420
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
#include <queue>
using namespace std;

using tbl = vector<vector<char>>;

int solve(const tbl &t, const int h, const int w, const int sh, const int sw)
{
  // 左，上，右，下方向の単位ベクトル
  const vector<int> dhs = {0, -1, 0, 1};
  const vector<int> dws = {1, 0, -1, 0};

  // visited[i][j]: タイル上の (i, j) 成分に到達可能か
  vector<vector<bool>> visited(h, vector<bool> (w, false));

  queue<pair<int, int>> q;
  q.push(make_pair(sh, sw));

  while (!q.empty())
  {
    pair<int, int> cur = q.front();
    int cur_h = cur.first;
    int cur_w = cur.second;
    visited[cur_h][cur_w] = true;
    q.pop();

    for (int i = 0; i < 4; ++i)
    {
      int next_h = cur_h + dhs[i];
      int next_w = cur_w + dws[i];
      // (next_h, next_w) がタイルの中なら
      if (0 <= next_h && next_h < h && 0 <= next_w && next_w < w)
      {
        // すでに訪問済みならスルー
        if (visited[next_h][next_w]) continue;

        // 黒いタイルならキューに追加
        if (t[next_h][next_w] == '.')
        {
          q.push(make_pair(next_h, next_w));
        }
      }
    }
  }
  
  int cnt = 0;
  for (int i = 0; i < h; ++i)
  {
    for (int j = 0; j < w; ++j)
    {
      if (visited[i][j]) ++cnt;
    }
  }
  return cnt;
}

int main() 
{
  int w, h;
  while (cin >> w >> h && w|h) 
  {
    tbl t(h, vector<char> (w));
    int sh, sw; // 開始位置が何行何列か
    for (int i = 0; i < h; ++i)
    {
      for (int j = 0; j < w; ++j)
      {
        cin >> t[i][j];
        if (t[i][j] == '@')
        {
          sh = i;
          sw = j;
        }
      }
    }
    cout << solve(t, h, w, sh, sw) << '\n';
  }
  return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 6516
final_rank: 12

code_snippet: /*
https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1130&lang=jp

15分ほどで実装できた。char型とstring型の使い方をごちゃまぜにしてしまい少しはまった。
また進むことのできる方角をdxやdyなどの配列で持っておくという発想は初めて習ったので、
今後活用していきたい。
 */
#include <cmath>
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;

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

int solve(vector<vector<char>> state, int W, int H, int sx, int sy)
{
    int nx, ny;
    int num_v = 0;
    vector<vector<int>> done(W, vector<int>(H, 0));
    queue<pair<int, int>> que;
    que.push(make_pair(sx, sy));
    while (!que.empty())
    {
        pair<int, int> v = que.front();
        que.pop();
        for (int i = 0; i < 4; i++)
        {
            nx = v.first + dx[i];
            ny = v.second + dy[i];
            if ((0 <= nx) && (nx < W) && (0 <= ny) && (ny < H) && (state[nx][ny] != '#'))
                que.push(make_pair(nx, ny));
        }
        done[v.first][v.second] = 1;
        state[v.first][v.second] = '#';
    }

    for (auto d : done)
        for (auto f : d)
            num_v += f;
    return num_v;
}

int main()
{
    int W, H, sx, sy;
    string t;
    while (cin >> W >> H)
    {
        if (W == 0 && H == 0)
            break;

        vector<vector<char>> state(W, vector<char>(H));
        for (int j = 0; j < H; j++)
        {
            cin >> t;
            for (int i = 0; i < W; i++)
            {
                state[i][j] = t[i];
                if (t[i] == '@')
                {
                    sx = i;
                    sy = j;
                }
            }
        }
        cout << solve(state, W, H, sx, sy) << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 6332
final_rank: 10

code_snippet: #include <cmath>
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;

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

int solve(vector<vector<char>> state, int W, int H, int sx, int sy)
{
    int nx, ny;
    int num_v = 0;
    vector<vector<int>> done(W, vector<int>(H, 0));
    queue<pair<int, int>> que;
    que.push(make_pair(sx, sy));
    while (!que.empty())
    {
        pair<int, int> v = que.front();
        que.pop();
        for (int i = 0; i < 4; i++)
        {
            nx = v.first + dx[i];
            ny = v.second + dy[i];
            if ((0 <= nx) && (nx < W) && (0 <= ny) && (ny < H) && (state[nx][ny] != '#'))
                que.push(make_pair(nx, ny));
        }
        done[v.first][v.second] = 1;
        state[v.first][v.second] = '#';
    }

    for (auto d : done)
        for (auto f : d)
            num_v += f;
    return num_v;
}

int main()
{
    int W, H, sx, sy;
    string t;
    while (cin >> W >> H)
    {
        if (W == 0 && H == 0)
            break;

        vector<vector<char>> state(W, vector<char>(H));
        for (int j = 0; j < H; j++)
        {
            cin >> t;
            for (int i = 0; i < W; i++)
            {
                state[i][j] = t[i];
                if (t[i] == '@')
                {
                    sx = i;
                    sy = j;
                }
            }
        }
        cout << solve(state, W, H, sx, sy) << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 6472
final_rank: 11

code_snippet: /* C++ */
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef long double ld;
typedef pair<ll, ll> pint;
const ll MOD = 1000000007;
const ll INF = 9223372036854775807/2;
#define rep(i, n) for(ll i = (ll)0; i < (ll)(n); i++)
#define Rep(i, s, t) for(ll i = (ll)(s); i < (ll)(t); i++)
#define ALL(a)  (a).begin(),(a).end()
#define uniq(x) (x).erase(unique((x).begin(), (x).end()), (x).end());
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define PI 3.14159265358979323846
#define ifYN(x) cout << (x ? "Yes" : "No") << "\n"
ll dx[8] = {-1, 1, 0, 0, -1, -1, 1, 1};
ll dy[8] = {0, 0, -1, 1, -1, 1, -1, 1};

template<class T> inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

template<class T> inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

ll Len(ll n) {
  if (n == 0) return 1;
  ll s = 0;
  while (n != 0) s++, n /= 10;
  return s;
}

ll Sint(ll n) {
  ll ans = 0;
  while (n != 0) ans += n % 10, n /= 10;
  return ans;
}

ll GCD(ll a, ll b) {
  return b ? GCD(b, a % b) : a;
}

ll LCM(ll a, ll b){
  return a / GCD(a, b) * b;
}

ll POW(ll a, ll n, ll mod = INF) {
  ll res = 1;
  while (n > 0) {
    if (n & 1) res = res * a % mod;
    a = a * a % mod;
    n >>= 1;
  }
  return res;
}

void dis(vector<ll> V) {
  rep(i, V.size()) cout << (i ? " " : "") << V[i];
  cout << endl;
}

void dis2(vector<vector<ll> > v) {
  rep (i, v.size()) {
    rep (j, v[0].size()) cout << v[i][j] << ' ';
    cout << endl;
  }
}

ll VECTORSUM(vector<ll> V) {
  ll ans = 0;
  rep(i, V.size()) ans += V[i];
  return ans;
}

string SUBSTR(string S, ll start, ll to) {
  string ans = "";
  Rep(i, start-1, to) ans += S[i];
  return ans;
}

ll StoI(string S) {
  reverse(ALL(S));
  ll len = 1;
  ll ans = 0;
  rep(i, S.size()) {
    ans += len * (S[i]-'0');
    len *= 10;
  }
  return ans;
}



bool cmp(pint a, pint b) { return a.second < b.second; }

bool solve() {
  ll W, H; cin >> W >> H;
  if(W+H == 0) return false;
  vector<vector<char>> V(H, vector<char>(W));
  vector<vector<bool>> flag(H, vector<bool>(W, false));
  rep(i, H) rep(j, W) cin >> V[i][j];
  ll sx, sy;
  rep(i, H) rep(j, W) {
    if(V[i][j] == '@') sx = j, sy = i;
  }
  queue<pint> que;
  que.push(pint(sx, sy));
  while(!que.empty()) {
    auto c = que.front();
    que.pop();
    flag[c.second][c.first] = true;
    rep(i, 4) {
      ll nx = c.first + dx[i];
      ll ny = c.second + dy[i];
      if(nx < 0 || nx >= W || ny < 0 || ny >= H) continue;
      if(V[ny][nx] == '#') continue;
      if(flag[ny][nx]) continue;
      que.push(pint(nx, ny));
    }
  }
  ll ans = 0;
  rep(i, H) rep(j, W) if(flag[i][j]) ans++;
  cout << ans << endl;
  return true;
}

/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
int main() {
  IOS;
  while(1) {
    if(!solve()) break;
  }
}
accuracy: 1
time_ms: 80
memory_kb: 9612
final_rank: 13

code_snippet: #include <bits/stdc++.h>

#include <algorithm>
#include <array>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

    namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
        int ceil_pow2(int n) {
            int x = 0;
            while ((1U << x) < (unsigned int)(n)) x++;
            return x;
        }

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
        int bsf(unsigned int n) {
#ifdef _MSC_VER
            unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
            return __builtin_ctz(n);
#endif
        }

    }  // namespace internal

}  // namespace atcoder



#include <utility>

namespace atcoder {

    namespace internal {

// @param m `1 <= m`
// @return x mod m
        constexpr long long safe_mod(long long x, long long m) {
            x %= m;
            if (x < 0) x += m;
            return x;
        }

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
        struct barrett {
            unsigned int _m;
            unsigned long long im;

            // @param m `1 <= m < 2^31`
            barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

            // @return m
            unsigned int umod() const { return _m; }

            // @param a `0 <= a < m`
            // @param b `0 <= b < m`
            // @return `a * b % m`
            unsigned int mul(unsigned int a, unsigned int b) const {
                // [1] m = 1
                // a = b = im = 0, so okay

                // [2] m >= 2
                // im = ceil(2^64 / m)
                // -> im * m = 2^64 + r (0 <= r < m)
                // let z = a*b = c*m + d (0 <= c, d < m)
                // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
                // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
                // ((ab * im) >> 64) == c or c + 1
                unsigned long long z = a;
                z *= b;
#ifdef _MSC_VER
                unsigned long long x;
        _umul128(z, im, &x);
#else
                unsigned long long x =
                        (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
                unsigned int v = (unsigned int)(z - x * _m);
                if (_m <= v) v += _m;
                return v;
            }
        };

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
        constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
            if (m == 1) return 0;
            unsigned int _m = (unsigned int)(m);
            unsigned long long r = 1;
            unsigned long long y = safe_mod(x, m);
            while (n) {
                if (n & 1) r = (r * y) % _m;
                y = (y * y) % _m;
                n >>= 1;
            }
            return r;
        }

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
        constexpr bool is_prime_constexpr(int n) {
            if (n <= 1) return false;
            if (n == 2 || n == 7 || n == 61) return true;
            if (n % 2 == 0) return false;
            long long d = n - 1;
            while (d % 2 == 0) d /= 2;
            constexpr long long bases[3] = {2, 7, 61};
            for (long long a : bases) {
                long long t = d;
                long long y = pow_mod_constexpr(a, t, n);
                while (t != n - 1 && y != 1 && y != n - 1) {
                    y = y * y % n;
                    t <<= 1;
                }
                if (y != n - 1 && t % 2 == 0) {
                    return false;
                }
            }
            return true;
        }
        template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
        constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
            a = safe_mod(a, b);
            if (a == 0) return {b, 0};

            // Contracts:
            // [1] s - m0 * a = 0 (mod b)
            // [2] t - m1 * a = 0 (mod b)
            // [3] s * |m1| + t * |m0| <= b
            long long s = b, t = a;
            long long m0 = 0, m1 = 1;

            while (t) {
                long long u = s / t;
                s -= t * u;
                m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

                // [3]:
                // (s - t * u) * |m1| + t * |m0 - m1 * u|
                // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
                // = s * |m1| + t * |m0| <= b

                auto tmp = s;
                s = t;
                t = tmp;
                tmp = m0;
                m0 = m1;
                m1 = tmp;
            }
            // by [3]: |m0| <= b/g
            // by g != b: |m0| < b/g
            if (m0 < 0) m0 += b / s;
            return {s, m0};
        }

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
        constexpr int primitive_root_constexpr(int m) {
            if (m == 2) return 1;
            if (m == 167772161) return 3;
            if (m == 469762049) return 3;
            if (m == 754974721) return 11;
            if (m == 998244353) return 3;
            int divs[20] = {};
            divs[0] = 2;
            int cnt = 1;
            int x = (m - 1) / 2;
            while (x % 2 == 0) x /= 2;
            for (int i = 3; (long long)(i)*i <= x; i += 2) {
                if (x % i == 0) {
                    divs[cnt++] = i;
                    while (x % i == 0) {
                        x /= i;
                    }
                }
            }
            if (x > 1) {
                divs[cnt++] = x;
            }
            for (int g = 2;; g++) {
                bool ok = true;
                for (int i = 0; i < cnt; i++) {
                    if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                        ok = false;
                        break;
                    }
                }
                if (ok) return g;
            }
        }
        template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

    }  // namespace internal

}  // namespace atcoder


#include <algorithm>

#include <vector>

namespace atcoder {

    namespace internal {

        template <class T> struct simple_queue {
            std::vector<T> payload;
            int pos = 0;
            void reserve(int n) { payload.reserve(n); }
            int size() const { return int(payload.size()) - pos; }
            bool empty() const { return pos == int(payload.size()); }
            void push(const T& t) { payload.push_back(t); }
            T& front() { return payload[pos]; }
            void clear() {
                payload.clear();
                pos = 0;
            }
            void pop() { pos++; }
        };

    }  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <limits>
#include <queue>
#include <vector>

namespace atcoder {

    template <class Cap> struct mf_graph {
    public:
        mf_graph() : _n(0) {}
        mf_graph(int n) : _n(n), g(n) {}

        int add_edge(int from, int to, Cap cap) {
            assert(0 <= from && from < _n);
            assert(0 <= to && to < _n);
            assert(0 <= cap);
            int m = int(pos.size());
            pos.push_back({from, int(g[from].size())});
            int from_id = int(g[from].size());
            int to_id = int(g[to].size());
            if (from == to) to_id++;
            g[from].push_back(_edge{to, to_id, cap});
            g[to].push_back(_edge{from, from_id, 0});
            return m;
        }

        struct edge {
            int from, to;
            Cap cap, flow;
        };

        edge get_edge(int i) {
            int m = int(pos.size());
            assert(0 <= i && i < m);
            auto _e = g[pos[i].first][pos[i].second];
            auto _re = g[_e.to][_e.rev];
            return edge{pos[i].first, _e.to, _e.cap + _re.cap, _re.cap};
        }
        std::vector<edge> edges() {
            int m = int(pos.size());
            std::vector<edge> result;
            for (int i = 0; i < m; i++) {
                result.push_back(get_edge(i));
            }
            return result;
        }
        void change_edge(int i, Cap new_cap, Cap new_flow) {
            int m = int(pos.size());
            assert(0 <= i && i < m);
            assert(0 <= new_flow && new_flow <= new_cap);
            auto& _e = g[pos[i].first][pos[i].second];
            auto& _re = g[_e.to][_e.rev];
            _e.cap = new_cap - new_flow;
            _re.cap = new_flow;
        }

        Cap flow(int s, int t) {
            return flow(s, t, std::numeric_limits<Cap>::max());
        }
        Cap flow(int s, int t, Cap flow_limit) {
            assert(0 <= s && s < _n);
            assert(0 <= t && t < _n);
            assert(s != t);

            std::vector<int> level(_n), iter(_n);
            internal::simple_queue<int> que;

            auto bfs = [&]() {
                std::fill(level.begin(), level.end(), -1);
                level[s] = 0;
                que.clear();
                que.push(s);
                while (!que.empty()) {
                    int v = que.front();
                    que.pop();
                    for (auto e : g[v]) {
                        if (e.cap == 0 || level[e.to] >= 0) continue;
                        level[e.to] = level[v] + 1;
                        if (e.to == t) return;
                        que.push(e.to);
                    }
                }
            };
            auto dfs = [&](auto self, int v, Cap up) {
                if (v == s) return up;
                Cap res = 0;
                int level_v = level[v];
                for (int& i = iter[v]; i < int(g[v].size()); i++) {
                    _edge& e = g[v][i];
                    if (level_v <= level[e.to] || g[e.to][e.rev].cap == 0) continue;
                    Cap d =
                            self(self, e.to, std::min(up - res, g[e.to][e.rev].cap));
                    if (d <= 0) continue;
                    g[v][i].cap += d;
                    g[e.to][e.rev].cap -= d;
                    res += d;
                    if (res == up) break;
                }
                return res;
            };

            Cap flow = 0;
            while (flow < flow_limit) {
                bfs();
                if (level[t] == -1) break;
                std::fill(iter.begin(), iter.end(), 0);
                while (flow < flow_limit) {
                    Cap f = dfs(dfs, t, flow_limit - flow);
                    if (!f) break;
                    flow += f;
                }
            }
            return flow;
        }

        std::vector<bool> min_cut(int s) {
            std::vector<bool> visited(_n);
            internal::simple_queue<int> que;
            que.push(s);
            while (!que.empty()) {
                int p = que.front();
                que.pop();
                visited[p] = true;
                for (auto e : g[p]) {
                    if (e.cap && !visited[e.to]) {
                        visited[e.to] = true;
                        que.push(e.to);
                    }
                }
            }
            return visited;
        }

    private:
        int _n;
        struct _edge {
            int to, rev;
            Cap cap;
        };
        std::vector<std::pair<int, int>> pos;
        std::vector<std::vector<_edge>> g;
    };

}  // namespace atcoder



#include <cassert>
#include <vector>


#include <algorithm>
#include <cassert>
#include <vector>


using namespace std;
using namespace atcoder;
#define ll long long
#define FOR(i, begin, end) for(int i=(begin),i##_end_=(end);i<i##_end_;i++)
#define IFOR(i, begin, end) for(int i=(end)-1,i##_begin_=(begin);i>=i##_begin_;i--)
#define REP(i, n) FOR(i,0,n)
#define IREP(i, n) IFOR(i,0,n)

void solve(){
    int h, w;
    vector<vector<char>> maze;
    vector<int> dh = {-1, 0, 0, 1};
    vector<int> dw = {0, -1, 1, 0};
    int curh, curw;
    char c;
    while(true){
        cin >> w >> h;
        if(h==0 && w==0) break;
        maze = vector<vector<char>>(h + 2, vector<char>(w + 2, '#'));
        REP(i, w) maze[0][i] = '#';
        FOR(hh, 1, h + 1){
            FOR(ww, 1, w + 1){
                cin >> c;
                if(c == '@'){
                    curh = hh;
                    curw = ww;
                    c = '.';
                }
                maze[hh][ww] = c;
            }
        }
        REP(i, w) maze[h+1][i] = '#';
        int nodenum = (w+2) * (h+2) + 2;
        int nodes = nodenum - 2;
        int nodet = nodenum - 1;
        auto hw2num = [&](int hh, int ww){ return hh * (w+2) + ww; };
        mf_graph<int> mf(nodenum);
        REP(hh, h+2){
            REP(ww, w+2){
                if(maze[hh][ww] == '#') continue;
                mf.add_edge(hw2num(hh, ww), nodet, 1);
                REP(di, dh.size()){
                    mf.add_edge(hw2num(hh, ww), hw2num(hh+dh[di], ww+dw[di]), h*w);
                }
            }
            mf.add_edge(nodes, hw2num(curh, curw), h*w);
        }
        cout << mf.flow(nodes, nodet) << "\n";
    }

}

int main(int argc, char *argv[]) {
    solve();
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3512
final_rank: 6

code_snippet: #include <bits/stdc++.h>

#include <algorithm>
#include <array>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

    namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
        int ceil_pow2(int n) {
            int x = 0;
            while ((1U << x) < (unsigned int)(n)) x++;
            return x;
        }

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
        int bsf(unsigned int n) {
#ifdef _MSC_VER
            unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
            return __builtin_ctz(n);
#endif
        }

    }  // namespace internal

}  // namespace atcoder



#include <utility>

namespace atcoder {

    namespace internal {

// @param m `1 <= m`
// @return x mod m
        constexpr long long safe_mod(long long x, long long m) {
            x %= m;
            if (x < 0) x += m;
            return x;
        }

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
        struct barrett {
            unsigned int _m;
            unsigned long long im;

            // @param m `1 <= m < 2^31`
            barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

            // @return m
            unsigned int umod() const { return _m; }

            // @param a `0 <= a < m`
            // @param b `0 <= b < m`
            // @return `a * b % m`
            unsigned int mul(unsigned int a, unsigned int b) const {
                // [1] m = 1
                // a = b = im = 0, so okay

                // [2] m >= 2
                // im = ceil(2^64 / m)
                // -> im * m = 2^64 + r (0 <= r < m)
                // let z = a*b = c*m + d (0 <= c, d < m)
                // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
                // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
                // ((ab * im) >> 64) == c or c + 1
                unsigned long long z = a;
                z *= b;
#ifdef _MSC_VER
                unsigned long long x;
        _umul128(z, im, &x);
#else
                unsigned long long x =
                        (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
                unsigned int v = (unsigned int)(z - x * _m);
                if (_m <= v) v += _m;
                return v;
            }
        };

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
        constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
            if (m == 1) return 0;
            unsigned int _m = (unsigned int)(m);
            unsigned long long r = 1;
            unsigned long long y = safe_mod(x, m);
            while (n) {
                if (n & 1) r = (r * y) % _m;
                y = (y * y) % _m;
                n >>= 1;
            }
            return r;
        }

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
        constexpr bool is_prime_constexpr(int n) {
            if (n <= 1) return false;
            if (n == 2 || n == 7 || n == 61) return true;
            if (n % 2 == 0) return false;
            long long d = n - 1;
            while (d % 2 == 0) d /= 2;
            constexpr long long bases[3] = {2, 7, 61};
            for (long long a : bases) {
                long long t = d;
                long long y = pow_mod_constexpr(a, t, n);
                while (t != n - 1 && y != 1 && y != n - 1) {
                    y = y * y % n;
                    t <<= 1;
                }
                if (y != n - 1 && t % 2 == 0) {
                    return false;
                }
            }
            return true;
        }
        template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
        constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
            a = safe_mod(a, b);
            if (a == 0) return {b, 0};

            // Contracts:
            // [1] s - m0 * a = 0 (mod b)
            // [2] t - m1 * a = 0 (mod b)
            // [3] s * |m1| + t * |m0| <= b
            long long s = b, t = a;
            long long m0 = 0, m1 = 1;

            while (t) {
                long long u = s / t;
                s -= t * u;
                m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

                // [3]:
                // (s - t * u) * |m1| + t * |m0 - m1 * u|
                // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
                // = s * |m1| + t * |m0| <= b

                auto tmp = s;
                s = t;
                t = tmp;
                tmp = m0;
                m0 = m1;
                m1 = tmp;
            }
            // by [3]: |m0| <= b/g
            // by g != b: |m0| < b/g
            if (m0 < 0) m0 += b / s;
            return {s, m0};
        }

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
        constexpr int primitive_root_constexpr(int m) {
            if (m == 2) return 1;
            if (m == 167772161) return 3;
            if (m == 469762049) return 3;
            if (m == 754974721) return 11;
            if (m == 998244353) return 3;
            int divs[20] = {};
            divs[0] = 2;
            int cnt = 1;
            int x = (m - 1) / 2;
            while (x % 2 == 0) x /= 2;
            for (int i = 3; (long long)(i)*i <= x; i += 2) {
                if (x % i == 0) {
                    divs[cnt++] = i;
                    while (x % i == 0) {
                        x /= i;
                    }
                }
            }
            if (x > 1) {
                divs[cnt++] = x;
            }
            for (int g = 2;; g++) {
                bool ok = true;
                for (int i = 0; i < cnt; i++) {
                    if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                        ok = false;
                        break;
                    }
                }
                if (ok) return g;
            }
        }
        template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

    }  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

    namespace internal {

#ifndef _MSC_VER
        template <class T>
        using is_signed_int128 =
        typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                std::true_type,
                std::false_type>::type;

        template <class T>
        using is_unsigned_int128 =
        typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                std::true_type,
                std::false_type>::type;

        template <class T>
        using make_unsigned_int128 =
        typename std::conditional<std::is_same<T, __int128_t>::value,
                __uint128_t,
                unsigned __int128>;

        template <class T>
        using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                      is_signed_int128<T>::value ||
                                                      is_unsigned_int128<T>::value,
                std::true_type,
                std::false_type>::type;

        template <class T>
        using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                         std::is_signed<T>::value) ||
                                                        is_signed_int128<T>::value,
                std::true_type,
                std::false_type>::type;

        template <class T>
        using is_unsigned_int =
        typename std::conditional<(is_integral<T>::value &&
                                   std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                std::true_type,
                std::false_type>::type;

        template <class T>
        using to_unsigned = typename std::conditional<
                is_signed_int128<T>::value,
                make_unsigned_int128<T>,
                typename std::conditional<std::is_signed<T>::value,
                        std::make_unsigned<T>,
                        std::common_type<T>>::type>::type;

#else

        template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

        template <class T>
        using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

        template <class T>
        using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

        template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

    }  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif



#include <algorithm>
#include <cassert>
#include <tuple>
#include <vector>

namespace atcoder {

    long long pow_mod(long long x, long long n, int m) {
        assert(0 <= n && 1 <= m);
        if (m == 1) return 0;
        internal::barrett bt((unsigned int)(m));
        unsigned int r = 1, y = (unsigned int)(internal::safe_mod(x, m));
        while (n) {
            if (n & 1) r = bt.mul(r, y);
            y = bt.mul(y, y);
            n >>= 1;
        }
        return r;
    }

    long long inv_mod(long long x, long long m) {
        assert(1 <= m);
        auto z = internal::inv_gcd(x, m);
        assert(z.first == 1);
        return z.second;
    }

// (rem, mod)
    std::pair<long long, long long> crt(const std::vector<long long>& r,
                                        const std::vector<long long>& m) {
        assert(r.size() == m.size());
        int n = int(r.size());
        // Contracts: 0 <= r0 < m0
        long long r0 = 0, m0 = 1;
        for (int i = 0; i < n; i++) {
            assert(1 <= m[i]);
            long long r1 = internal::safe_mod(r[i], m[i]), m1 = m[i];
            if (m0 < m1) {
                std::swap(r0, r1);
                std::swap(m0, m1);
            }
            if (m0 % m1 == 0) {
                if (r0 % m1 != r1) return {0, 0};
                continue;
            }
            // assume: m0 > m1, lcm(m0, m1) >= 2 * max(m0, m1)

            // (r0, m0), (r1, m1) -> (r2, m2 = lcm(m0, m1));
            // r2 % m0 = r0
            // r2 % m1 = r1
            // -> (r0 + x*m0) % m1 = r1
            // -> x*u0*g % (u1*g) = (r1 - r0) (u0*g = m0, u1*g = m1)
            // -> x = (r1 - r0) / g * inv(u0) (mod u1)

            // im = inv(u0) (mod u1) (0 <= im < u1)
            long long g, im;
            std::tie(g, im) = internal::inv_gcd(m0, m1);

            long long u1 = (m1 / g);
            // |r1 - r0| < (m0 + m1) <= lcm(m0, m1)
            if ((r1 - r0) % g) return {0, 0};

            // u1 * u1 <= m1 * m1 / g / g <= m0 * m1 / g = lcm(m0, m1)
            long long x = (r1 - r0) / g % u1 * im % u1;

            // |r0| + |m0 * x|
            // < m0 + m0 * (u1 - 1)
            // = m0 + m0 * m1 / g - m0
            // = lcm(m0, m1)
            r0 += x * m0;
            m0 *= u1;  // -> lcm(m0, m1)
            if (r0 < 0) r0 += m0;
        }
        return {r0, m0};
    }

    long long floor_sum(long long n, long long m, long long a, long long b) {
        long long ans = 0;
        if (a >= m) {
            ans += (n - 1) * n * (a / m) / 2;
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        long long y_max = (a * n + b) / m, x_max = (y_max * m - b);
        if (y_max == 0) return ans;
        ans += (n - (x_max + a - 1) / a) * y_max;
        ans += floor_sum(y_max, a, m, (a - x_max % a) % a);
        return ans;
    }

}  // namespace atcoder


#include <algorithm>

#include <vector>

namespace atcoder {

    namespace internal {

        template <class T> struct simple_queue {
            std::vector<T> payload;
            int pos = 0;
            void reserve(int n) { payload.reserve(n); }
            int size() const { return int(payload.size()) - pos; }
            bool empty() const { return pos == int(payload.size()); }
            void push(const T& t) { payload.push_back(t); }
            T& front() { return payload[pos]; }
            void clear() {
                payload.clear();
                pos = 0;
            }
            void pop() { pos++; }
        };

    }  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <limits>
#include <queue>
#include <vector>

namespace atcoder {

    template <class Cap> struct mf_graph {
    public:
        mf_graph() : _n(0) {}
        mf_graph(int n) : _n(n), g(n) {}

        int add_edge(int from, int to, Cap cap) {
            assert(0 <= from && from < _n);
            assert(0 <= to && to < _n);
            assert(0 <= cap);
            int m = int(pos.size());
            pos.push_back({from, int(g[from].size())});
            int from_id = int(g[from].size());
            int to_id = int(g[to].size());
            if (from == to) to_id++;
            g[from].push_back(_edge{to, to_id, cap});
            g[to].push_back(_edge{from, from_id, 0});
            return m;
        }

        struct edge {
            int from, to;
            Cap cap, flow;
        };

        edge get_edge(int i) {
            int m = int(pos.size());
            assert(0 <= i && i < m);
            auto _e = g[pos[i].first][pos[i].second];
            auto _re = g[_e.to][_e.rev];
            return edge{pos[i].first, _e.to, _e.cap + _re.cap, _re.cap};
        }
        std::vector<edge> edges() {
            int m = int(pos.size());
            std::vector<edge> result;
            for (int i = 0; i < m; i++) {
                result.push_back(get_edge(i));
            }
            return result;
        }
        void change_edge(int i, Cap new_cap, Cap new_flow) {
            int m = int(pos.size());
            assert(0 <= i && i < m);
            assert(0 <= new_flow && new_flow <= new_cap);
            auto& _e = g[pos[i].first][pos[i].second];
            auto& _re = g[_e.to][_e.rev];
            _e.cap = new_cap - new_flow;
            _re.cap = new_flow;
        }

        Cap flow(int s, int t) {
            return flow(s, t, std::numeric_limits<Cap>::max());
        }
        Cap flow(int s, int t, Cap flow_limit) {
            assert(0 <= s && s < _n);
            assert(0 <= t && t < _n);
            assert(s != t);

            std::vector<int> level(_n), iter(_n);
            internal::simple_queue<int> que;

            auto bfs = [&]() {
                std::fill(level.begin(), level.end(), -1);
                level[s] = 0;
                que.clear();
                que.push(s);
                while (!que.empty()) {
                    int v = que.front();
                    que.pop();
                    for (auto e : g[v]) {
                        if (e.cap == 0 || level[e.to] >= 0) continue;
                        level[e.to] = level[v] + 1;
                        if (e.to == t) return;
                        que.push(e.to);
                    }
                }
            };
            auto dfs = [&](auto self, int v, Cap up) {
                if (v == s) return up;
                Cap res = 0;
                int level_v = level[v];
                for (int& i = iter[v]; i < int(g[v].size()); i++) {
                    _edge& e = g[v][i];
                    if (level_v <= level[e.to] || g[e.to][e.rev].cap == 0) continue;
                    Cap d =
                            self(self, e.to, std::min(up - res, g[e.to][e.rev].cap));
                    if (d <= 0) continue;
                    g[v][i].cap += d;
                    g[e.to][e.rev].cap -= d;
                    res += d;
                    if (res == up) break;
                }
                return res;
            };

            Cap flow = 0;
            while (flow < flow_limit) {
                bfs();
                if (level[t] == -1) break;
                std::fill(iter.begin(), iter.end(), 0);
                while (flow < flow_limit) {
                    Cap f = dfs(dfs, t, flow_limit - flow);
                    if (!f) break;
                    flow += f;
                }
            }
            return flow;
        }

        std::vector<bool> min_cut(int s) {
            std::vector<bool> visited(_n);
            internal::simple_queue<int> que;
            que.push(s);
            while (!que.empty()) {
                int p = que.front();
                que.pop();
                visited[p] = true;
                for (auto e : g[p]) {
                    if (e.cap && !visited[e.to]) {
                        visited[e.to] = true;
                        que.push(e.to);
                    }
                }
            }
            return visited;
        }

    private:
        int _n;
        struct _edge {
            int to, rev;
            Cap cap;
        };
        std::vector<std::pair<int, int>> pos;
        std::vector<std::vector<_edge>> g;
    };

}  // namespace atcoder



#include <cassert>
#include <vector>


#include <algorithm>
#include <cassert>
#include <vector>


using namespace std;
using namespace atcoder;
#define ll long long
#define FOR(i, begin, end) for(int i=(begin),i##_end_=(end);i<i##_end_;i++)
#define IFOR(i, begin, end) for(int i=(end)-1,i##_begin_=(begin);i>=i##_begin_;i--)
#define REP(i, n) FOR(i,0,n)
#define IREP(i, n) IFOR(i,0,n)

void solve(){
    int h, w;
    vector<vector<char>> maze;
    vector<int> dh = {-1, 0, 0, 1};
    vector<int> dw = {0, -1, 1, 0};
    int curh, curw;
    char c;
    while(true){
        cin >> w >> h;
        if(h==0 && w==0) break;
        maze = vector<vector<char>>(h + 2, vector<char>(w + 2, '#'));
        REP(i, w) maze[0][i] = '#';
        FOR(hh, 1, h + 1){
            FOR(ww, 1, w + 1){
                cin >> c;
                if(c == '@'){
                    curh = hh;
                    curw = ww;
                    c = '.';
                }
                maze[hh][ww] = c;
            }
        }
        REP(i, w) maze[h+1][i] = '#';
        int nodenum = (w+2) * (h+2) + 2;
        int nodes = nodenum - 2;
        int nodet = nodenum - 1;
        auto hw2num = [&](int hh, int ww){ return hh * (w+2) + ww; };
        mf_graph<int> mf(nodenum);
        REP(hh, h+2){
            REP(ww, w+2){
                if(maze[hh][ww] == '#') continue;
                mf.add_edge(hw2num(hh, ww), nodet, 1);
                REP(di, dh.size()){
                    mf.add_edge(hw2num(hh, ww), hw2num(hh+dh[di], ww+dw[di]), h*w);
                }
            }
            mf.add_edge(nodes, hw2num(curh, curw), h*w);
        }
        cout << mf.flow(nodes, nodet) << "\n";
    }

}

int main(int argc, char *argv[]) {
    solve();
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3532
final_rank: 3