#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = 10, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int n, r;
struct Point
{
int x, y;
double dis;
bool operator < (const Point&b)const
{
return dis > b.dis;
}
}P[3600]; int pnum;
int d[405][405];
void init()
{
pnum = 0;
for (int i = -30; i <= 30; ++i)
{
for (int j = -30; j <= 30; ++j)
{
double dis = sqrt(i*i + j*j);
if (dis > r - 1 && dis <= r)
{
++pnum;
P[pnum].x = i;
P[pnum].y = j;
P[pnum].dis = dis;
}
}
}
sort(P + 1, P + pnum + 1);
//++pnum; P[pnum].x = 0; P[pnum].y = 0;
for (int i = 1; i <= pnum; ++i)
{
for (int j = i; j <= pnum; ++j)
{
d[i][j] = (P[i].x - P[j].x)*(P[i].x - P[j].x)
+ (P[i].y - P[j].y)*(P[i].y - P[j].y);
d[j][i] = d[i][j];
}
}
}
int R; int len;
int a[10], A[10];
int ans;
void dfs(int p,int num,int dis)
{
if (num == n)
{
if (dis <= ans)return;
ans = dis;
MC(A, a);
return;
}
if (p > pnum)return;
//int more = (n - num)*num + (n - num)*(n - num - 1) / 2;
//if (dis + more*R <= ans)return;
int top = min(pnum, p + len);
for (int i = p; i <= top; ++i)
{
int tmp = dis;
for (int j = 1; j <= num; ++j)tmp += d[i][a[j]];
double more = 1.01*tmp / num*(n-1)*(n - num);
if (dis + more < ans)continue;
a[num + 1] = i; dfs(i, num + 1, tmp);
}
}
int main()
{
while (~scanf("%d%d", &n, &r))
{
R = (r + r)*(r + r); len = 10;
init();
ans = 0;
dfs(1, 0, 0);
printf("%d\n", ans);
for (int i = 1; i <= n; ++i)
{
printf("%d %d\n", P[A[i]].x, P[A[i]].y);
}
}
return 0;
}
/*
【trick&&吐槽】
1,压缩搜索步长是个剪枝的好技巧
2,剪枝的估价函数要好好设计。
3,这题不能按照过程值的优劣做剪枝,因为是错误的。
4,我们并不需要考虑原点。
【题意】
给你一个网格图,我们只在整点放棋子。
有n(2<=n<=8)个点,它们距离原点的最远距离为r(1<=r<=30)
让你求出一个点集。使得两两之间的距离尽可能远。
【类型】
贪心+爆搜
【分析】
猜想:我们只要贪心,选择的点的范围在[r-1,r]之间即可。
然而,这些点的数量依然很多,直接爆搜还是很可怕。
这里运用贪心猜点位置,+估价函数剪枝和搜索步长剪枝
*/