// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0569

#include <iostream>
#include <vector>

using namespace std;

enum block {BUILDING, SPACE};

class Point {
public:
	int x;
	int y;
	Point(int aX, int aY) {
		x = aX, y = aY;
	}
	Point operator+(const Point& other) const {
		return Point(x + other.x, y + other.y);
	};
	bool operator==(const Point& other) const {
		return (x == other.x && y == other.y);
	};
};

vector<Point> listUpSurroundingBlocks(int W, int H, const Point& position);
bool isInMap(int W, int H, const Point& position);
bool isContained(const vector<Point>& points, const Point& p);

int main() {
	int W, H;
	cin >> W;
	cin >> H;
	block** map = new block*[W+2];
	bool** canReach = new bool*[W + 2];
	for (int x = 0; x < W + 2; x++) {
		map[x] = new block[H + 2];
		canReach[x] = new bool[H + 2];
	}
	
	for (int y = 0; y < H + 2; y++) {
		for (int x = 0; x < W + 2; x++) {	
			map[x][y] = SPACE;
			canReach[x][y] = false;
			if (x >= 1 && y >= 1 && x <= W && y <= H) {
				int isBuilding;
				cin >> isBuilding;
				if (isBuilding) {
					map[x][y] = BUILDING;
				}
			}
		}
	}
/*
	for (int y = 0; y < H + 2; y++) {
		if (y % 2 == 1) {
			cout << " ";
		}
		for (int x = 0; x < W + 2; x++) {	
			cout << (map[x][y] == BUILDING ? "1" : "0") << " ";
		}
		cout << endl;
	}
	cout << endl;
*/
	Point seed(0,0);
	vector<Point> buff;
	while(true) {
		canReach[seed.x][seed.y] = true;

		vector<Point> surroundings = listUpSurroundingBlocks(W, H, seed);
		for (auto it = surroundings.begin(); it != surroundings.end(); ++it) {
			int x = (*it).x, y = (*it).y;
			if (map[x][y] == SPACE && canReach[x][y] != true && !isContained(buff, *it)) {
				buff.push_back(*it);
			}
		}
		if (buff.empty()) {
			break;
		} else {
			seed = buff.back();
			buff.pop_back();
		}
	}
/*
	for (int y = 0; y < H + 2; y++) {
		if (y % 2 == 1) {
			cout << " ";
		}
		for (int x = 0; x < W + 2; x++) {
			cout << (canReach[x][y] == false ? "1" : "0") << " ";
		}
		cout << endl;
	}
	cout << endl;
*/
	int lengthOfIllumination = 0;
	for (int y = 0; y < H + 2; y++) {
		for (int x = 0; x < W + 2; x++) {
			if (!canReach[x][y]) {
				vector<Point> surroundings = listUpSurroundingBlocks(W, H, Point(x, y));
				for (auto it = surroundings.begin(); it != surroundings.end(); ++it) {
					if (canReach[(*it).x][(*it).y]) {
						lengthOfIllumination++;
					}
				}
			}
		}
	}

	cout << lengthOfIllumination << endl;

	for (int x = 0; x < W + 2; x++) {
		delete[] map[x];
	}
	delete[] map;

//	int wait;
//	cin >> wait;

	return 0;
}

vector<Point> listUpSurroundingBlocks(int W, int H, const Point& position) {
	Point surround[] = { Point(1,0), Point(-1,0), Point(-1,1), Point(0,1), Point(-1,-1), Point(0,-1) };
	if (position.y % 2 == 1) {
		for (int i = 0; i < 6; i++) {
			if (surround[i].y == 1 || surround[i].y == -1) {
				surround[i].x++;
			}
		}
	}
	
	vector<Point> result;
	for (int i = 0; i < 6; i++) {
		Point tmp = position + surround[i];
		if (isInMap(W, H, tmp)) {
			result.push_back(tmp);
		}
	}
	return result;
}

bool isInMap(int W, int H, const Point& position) {
	if (0 <= position.x && position.x <= W + 1 && 0 <= position.y && position.y <= H + 1) {
		return true;
	} else {
		return false;
	}
}

bool isContained(const vector<Point>& points, const Point& p) {
	for (auto it = points.begin(); it != points.end(); ++it) {
		if (p == *it) {
			return true;
		}
	}
	return false;
}

Measured memory_bytes: 3140