import std; void main () { // 逆を考える。 // 任意の移動経路について、パスになってさえいればそれが最短になるような配置が存在するかもしれない。 // パス列挙はできる。無駄なパスをどう検出するかが悩みどころ。->できそう? int H, W; readln.read(H, W); auto S = () { int i, j; readln.read(i, j); i--, j--; return tuple(i, j); }(); auto G = () { int i, j; readln.read(i, j); i--, j--; return tuple(i, j); }(); bool is_in (int y, int x) { return 0 <= y && y < H && 0 <= x && x < W; } const auto dxy = [ [-1, 0], [1, 0], [0, 1], [0, -1], ]; int ans = 0; auto vis = new bool[][](H, W); void dfs (int y, int x) { if (G[0] == y && G[1] == x) { // 4マス固まっていたらダメ? bool ok = true; foreach (i; 0..H) { foreach (j; 0..W) { if (!vis[i][j]) continue; int c = 0; foreach (d; dxy) { int ni = i + d[0], nj = j + d[1]; if (is_in(ni, nj) && vis[ni][nj]) c++; } if (3 <= c) ok = false; } } // スタート、ゴールに触れてるのに無視したらダメ? int gc = 0; foreach (d; dxy) { int ny = G[0] + d[0], nx = G[1] + d[1]; if (is_in(ny, nx) && vis[ny][nx]) gc++; } int sc = 0; foreach (d; dxy) { int ny = S[0] + d[0], nx = S[1] + d[1]; if (is_in(ny, nx) && vis[ny][nx]) sc++; } if (2 <= gc || 2 <= sc) { ok = false; } if (ok) { ans++; } return; } foreach (d; dxy) { int ny = y + d[0], nx = x + d[1]; if (is_in(ny, nx) && !vis[ny][nx]) { vis[ny][nx] = true; dfs(ny, nx); vis[ny][nx] = false; } } } vis[S[0]][S[1]] = true; dfs(S[0], S[1]); writeln(ans); } void read (T...) (string S, ref T args) { import std.conv : to; import std.array : split; auto buf = S.split; foreach (i, ref arg; args) { arg = buf[i].to!(typeof(arg)); } }