#include <iostream>

using namespace std;

typedef struct{
	int color;
	bool is_checked;
} building_t;

inline int xy(const int _x, const int _y, const int _W){ return _x + _y * (_W + 2); }
inline int xLeftOblique(const int _x, const int _y){ return _x - (_y+1)%2; }
inline int xRightOblique(const int _x, const int _y){ return _x + _y%2; }

bool isSurrounded(building_t *_buildings, int *_index, int *_memo, const int _x, const int _y, const int _W){
	int coordinate = xy(_x, _y, _W);
	building_t tmp = _buildings[coordinate];

	// 建物があるなら true を返す
	if(tmp.color == 1) return true;

	// 地図外なら false を返す
	if(tmp.color == -1) return false;

	// 隣接マスが地図外なら false を返す
	// 奇数行と偶数行で隣接の座標の規則が異なるので注意
	const int xlo = xLeftOblique(_x, _y);
	const int xro = xRightOblique(_x, _y);
	if(_buildings[xy(xlo,  _y-1, _W)].color == -1){ _buildings[coordinate].color = -1; return false; }	//左上
	if(_buildings[xy(xro,  _y-1, _W)].color == -1){ _buildings[coordinate].color = -1; return false; }	//右上
	if(_buildings[xy(_x-1, _y,   _W)].color == -1){ _buildings[coordinate].color = -1; return false; }	//左
	if(_buildings[xy(_x+1, _y,   _W)].color == -1){ _buildings[coordinate].color = -1; return false; }	//右
	if(_buildings[xy(xlo,  _y+1, _W)].color == -1){ _buildings[coordinate].color = -1; return false; }	//左下
	if(_buildings[xy(xro,  _y+1, _W)].color == -1){ _buildings[coordinate].color = -1; return false; }	//右下

	// 既に調べていたら true を返す
	if(tmp.is_checked) return true;

	// チェック済みであることをメモ
	_buildings[coordinate].is_checked = true;

	// 隣接マスを調べる（再帰呼び出し）
	// -> false が返ってきたら 地図外(-1)にして false を返す
	if(!isSurrounded(_buildings, _index, _memo, xlo,  _y-1, _W)){ _buildings[coordinate].color = -1; return false; }	// 左上
	if(!isSurrounded(_buildings, _index, _memo, xro,  _y-1, _W)){ _buildings[coordinate].color = -1; return false; }	// 右上
	if(!isSurrounded(_buildings, _index, _memo, _x-1, _y,   _W)){ _buildings[coordinate].color = -1; return false; }	// 左
	if(!isSurrounded(_buildings, _index, _memo, _x+1, _y,   _W)){ _buildings[coordinate].color = -1; return false; }	// 右
	if(!isSurrounded(_buildings, _index, _memo, xlo,  _y+1, _W)){ _buildings[coordinate].color = -1; return false; }	// 左下
	if(!isSurrounded(_buildings, _index, _memo, xro,  _y+1, _W)){ _buildings[coordinate].color = -1; return false; }	// 右下

	// すべてを通過したら囲まれているので true を返す
	_buildings[coordinate].color = 1;
	_memo[*_index] = coordinate;
	(*_index)++;
	return true;
}

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

	// 地図外のマスを余分に用意しておく -> 建物に囲まれた白マスがあるかチェックするのに使う
	const int W2 = W + 2;
	const int H2 = H + 2;

	building_t *buildings = new building_t[W2 * H2];

	// 建物の配置を入力
	// 地図外 -> -1, 建物なし(白) -> 0, 建物あり(灰色) -> 1
	for(int y=0; y<H2; y++){
		for(int x=0; x<W2; x++){
			const int coordinate = xy(x, y, W);
			if(x == 0 || x == W2 - 1 || y == 0 || y == H2 - 1) buildings[coordinate].color = -1;
			else cin >> buildings[coordinate].color;
			buildings[coordinate].is_checked = false;
		}
	}

	//cout << endl;
	/*for(int y=1; y<=H; y++){
		if(y%2 == 1) cout << " ";
		for(int x=1; x<=W; x++){
			cout << buildings[xy(x, y , W)].color << " ";
		}
		cout << endl;
	}*/

	int *memo = new int[W*H];
	// 囲まれているところを調べる -> 囲まれていたら灰色に変える
	// 探索範囲は x=2 〜 W-1, y=2 〜 H-1
	for(int y=1; y<=H; y++){
		for(int x=1; x<=W; x++){
			int index = 0;
			if(!isSurrounded(buildings, &index, memo, x, y, W)){
				for(int i=0; i<index; i++) buildings[memo[i]].color = -1;
			}
			//cout << "x=" << x << " ,y=" << y << endl;
		}
	}

	/*cout << endl;
	for(int y=1; y<=H; y++){
		if(y%2 == 1) cout << " ";
		for(int x=1; x<=W; x++){
			cout << buildings[xy(x, y , W)].color+1 << " ";
		}
		cout << endl;
	}*/

	// 壁面の長さを求める
	int answer = 0;
	for(int y=1; y<=H; y++){
		for(int x=1; x<=W; x++){
			// 建物がある場合は隣接を調べる
			if(buildings[xy(x, y, W)].color == 1){

			// -> 隣接が地図外(color == -1)なら長さ +1
				int xlo = xLeftOblique(x, y);
				int xro = xRightOblique(x, y);
				if(buildings[xy(xlo, y-1, W)].color <= 0) answer++;	//左上
				if(buildings[xy(xro, y-1, W)].color <= 0) answer++;	//右上
				if(buildings[xy(x-1, y,   W)].color <= 0) answer++;	//左
				if(buildings[xy(x+1, y  , W)].color <= 0) answer++;	//右
				if(buildings[xy(xlo, y+1, W)].color <= 0) answer++;	//左下
				if(buildings[xy(xro, y+1, W)].color <= 0) answer++;	//右下
			}
		}
	}

	cout << answer << endl;

	delete[] buildings;
	delete[] memo;
	return 0;
}

Measured memory_bytes: 1784