#include using namespace std; void print(vector> v) { cout << " ---> "; for (auto &it : v) { cout << "(" << it.first << ", " << it.second << ") "; } cout << "\n"; } const int N = 20 + 7; int n; long double radr; bool insidecircle[N][N]; bool intersectcircle[N][N]; bool potscot[N][N]; int maxhas; bool okplaceborder[N][N]; vector>>> dp[N]; vector papa[N]; vector> nw; vector keep; bool inscells(vector> current, int row, int mask) { nw.clear(); keep.clear(); keep.resize((int) current.size(), 1); for (int col = 0; col <= n; col++) { if (mask & (1 << col)) { // cout << " : " << row << " and " << col << "\n"; // if (row == 5 && col == 2) exit(0); nw.push_back({row, col}); for (int i = 0; i < (int) current.size(); i++) { auto &[r, c] = current[i]; assert(r < row); if (intersectcircle[row - r][abs(c - col)]) { return 0; } if (potscot[row - r][abs(c - col)]) { keep[i] = 0; } } } } for (int i = 0; i < (int) current.size(); i++) { auto &[r, c] = current[i]; if (r + radr <= row + 1 - radr) continue; // if (keep[i]) //////////////////////////////////////////////////////////////////////////////////////////// { nw.push_back({r, c}); } } sort(nw.begin(), nw.end()); return 1; } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n >> radr; if (radr <= 0.5) { cout << (n - 1) * (n - 1) << "\n"; for (int i = 1; i <= n - 1; i++) { for (int j = 1; j <= n - 1; j++) { cout << i << " " << j << "\n"; } } return 0; } for (int x = 0; x <= n; x++) { for (int y = 0; y <= n; y++) { insidecircle[x][y] = (x * x + y * y <= radr * radr); if (insidecircle[x][y]) maxhas = x; intersectcircle[x][y] = (x * x + y * y < 4 * radr * radr); } } for (int x = 0; x <= n; x++) { for (int y = 0; y <= n; y++) { potscot[x][y] = 1; for (int r = x; r <= n; r++) { for (int c = 0; c <= n; c++) { if (insidecircle[r][c] && !insidecircle[abs(x - r)][abs(y - c)]) { potscot[x][y] = 0; } } } } } for (int r = 1; r <= n; r++) { for (int c = 1; c <= n; c++) { okplaceborder[r][c] = (r - radr >= 0 && c - radr >= 0 && r + radr <= n && c + radr <= n); } } vector validmasks; for (int mask = 0; mask < (1 << (n + 1)); mask++) { bool valid = 1; vector who; for (int c = 0; c <= n; c++) if (mask & (1 << c)) who.push_back(c); for (auto &i : who) { valid &= (i + radr <= n && i - radr >= 0); } for (int i = 1; i < (int) who.size(); i++) { valid &= (who[i - 1] + radr <= who[i] - radr); } if (valid) validmasks.push_back(mask); } // for (auto &mask : validmasks) // { // for (int c = 0; c <= n; c++) // { // cout << !!(mask & (1 << c)); // } // cout << "\n"; // } // return 0; if (0) for (int r = 0; r <= n; r++) { for (int c = 0; c <= n; c++) { cout << okplaceborder[r][c] << " "; } cout << "\n"; } dp[0].push_back({0, {}}); for (int r = 0; r < n; r++) { // go from r to r + 1 map>, pair> mp; for (int i = 0; i < (int) dp[r].size(); i++) // for (auto &[coef, cells] : dp[r]) { auto &[coef, cells] = dp[r][i]; for (auto &mask : validmasks) { bool ok = 1; int cntbits = 0; for (int c = 0; c <= n; c++) { if (mask & (1 << c)) { ok &= okplaceborder[r + 1][c]; cntbits++; } } if (!ok) continue; ok &= inscells(cells, r + 1, mask); if (!ok) continue; if (mp.count(nw) && coef + cntbits <= mp[nw].first) continue; mp[nw].first = coef + cntbits; mp[nw].second = i; } } for (auto &it : mp) { dp[r + 1].push_back({it.second.first, it.first}); papa[r + 1].push_back(it.second.second); } } int sol = -1, cr = -1; for (int i = 0; i < (int) dp[n].size(); i++) { auto &it = dp[n][i]; if (it.first > sol) { sol = it.first; cr = i; } } if (0) for (int r = 0; r <= n; r++) { for (auto &it : dp[r]) { cout << r << ", " << it.first; print(it.second); } cout << "\n\n"; } // cout << "sol = " << sol << "\n"; set> all; for (int i = n; i >= 1; i--) { assert(0 <= cr && cr < (int) dp[i].size()); assert((int) dp[i].size() == (int) papa[i].size()); for (auto &it : dp[i][cr].second) { all.insert(it); } cr = papa[i][cr]; } assert(cr == 0); assert((int) all.size() == sol); cout << sol << "\n"; for (auto &it : all) { cout << it.first << " " << it.second << "\n"; } return 0; // cout << " : " << maxhas << "\n"; return 0; }