#include <iostream>
#include <vector>
#include <queue>
using namespace std;
// Offset để dịch tọa độ từ [-1000, 1000] sang [0, 2000]
const int OFFSET = 1000;
const int GRID_SIZE = 2005;
// Mảng đánh dấu vật cản và khoảng cách
int dist[GRID_SIZE][GRID_SIZE];
bool is_blocked[GRID_SIZE][GRID_SIZE];
struct Point {
int x, y;
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
long long D;
cin >> n >> D; // n <= 10^4, D <= 10^7
// Khởi tạo trạng thái ban đầu
for (int i = 0; i < GRID_SIZE; i++) {
for (int j = 0; j < GRID_SIZE; j++) {
dist[i][j] = -1;
is_blocked[i][j] = false;
}
}
// Đọc các ô bị chặn và đánh dấu
for (int i = 0; i < n; i++) {
int x, y;
cin >> x >> y; // Giá trị tuyệt đối của x và y nhỏ hơn 10^3
is_blocked[x + OFFSET][y + OFFSET] = true;
}
// BFS
queue<Point> q;
q.push({0 + OFFSET, 0 + OFFSET});
dist[0 + OFFSET][0 + OFFSET] = 0;
long long count = 0;
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};
while (!q.empty()) {
Point curr = q.front();
q.pop();
// Nếu khoảng cách đã đạt tới D thì không cần mở rộng thêm
if (dist[curr.x][curr.y] >= D) continue;
for (int i = 0; i < 4; i++) {
int nx = curr.x + dx[i];
int ny = curr.y + dy[i];
// Kiểm tra biên mảng và vật cản
if (nx >= 0 && nx < GRID_SIZE && ny >= 0 && ny < GRID_SIZE
&& !is_blocked[nx][ny] && dist[nx][ny] == -1) {
dist[nx][ny] = dist[curr.x][curr.y] + 1;
q.push({nx, ny});
}
}
}
// Đếm số tọa độ đã đi được
for (int i = 0; i < GRID_SIZE; i++) {
for (int j = 0; j < GRID_SIZE; j++) {
if (dist[i][j] != -1 && dist[i][j] <= D) {
count++;
}
}
}
cout << count << endl;
return 0;
}