把 1 2 3 ... 19 共19个整数排列成六角形状,如下:
* * *
* * * *
* * * * *
* * * *
* * *
要求每个直线上的数字之和必须相等。共有15条直线哦!
再给点线索吧!我们预先填好了2个数字,第一行的头两个数字是:15 13,参见图【p1.png】,黄色一行为所求。
请你填写出中间一行的5个数字。数字间用空格分开。
这是一行用空格分开的整数,请通过浏览器提交答案,不要填写任何多余的内容(比如说明性的文字等)
<img src="https://img-blog.csdn.net/20150315202424193?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU3Ryb25nTWFuVHdv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
public class A {
int[][] am = new int[15][19];
int[] bm = new int[15];
int[] col = new int[19];
int[][] line = { { 0, 1, 2 }, { 3, 4, 5, 6 }, { 7, 8, 9, 10, 11 },
{ 12, 13, 14, 15 }, { 16, 17, 18 }, { 0, 3, 7 }, { 1, 4, 8, 12 },
{ 2, 5, 9, 13, 16 }, { 6, 10, 14, 17 }, { 11, 15, 18 },
{ 2, 6, 11 }, { 1, 5, 10, 15 }, { 0, 4, 9, 14, 18 },
{ 3, 8, 13, 17 }, { 7, 12, 16 } };
void init() {
for (int i = 0; i < line.length; i++) {
for (int j = 0; j < line[i].length; j++) {
am[i][line[i][j]] = 1;
}
}
for (int i = 0; i < bm.length; i++)
bm[i] = 38;
for (int i = 0; i < col.length; i++)
col[i] = i;
}
void switch_row(int a, int b) {
if (a == b)
return;
for (int j = 0; j < am[a].length; j++) {
int tmp = am[a][j];
am[a][j] = am[b][j];
am[b][j] = tmp;
}
int tmp = bm[a];
bm[a] = bm[b];
bm[b] = tmp;
}
int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
// k列,用k行消i行
void xiao_yuan(int k, int i) {
int u = am[k][k];
int v = am[i][k];
if (u == 0 || v == 0)
return;
int g = gcd(Math.abs(u), Math.abs(v));
for (int j = 0; j < am[i].length; j++)
am[i][j] = am[i][j] * u / g - am[k][j] * v / g;
bm[i] = bm[i] * u / g - bm[k] * v / g;
}
void try_switch_col(int k) {
int w = k;
for (int j = k; j < am[k].length; j++) {
if (am[k][j] != 0) {
w = j;
break;
}
}
if (w == k)
return;
for (int i = 0; i < am.length; i++) {
int tmp = am[i][k];
am[i][k] = am[i][w];
am[i][w] = tmp;
tmp = col[k];
col[k] = col[w];
col[w] = tmp;
}
}
void gauss() {
for (int j = 0; j < am.length; j++) {
for (int i = j; i < am.length; i++) {
if (am[i][j] != 0) {
switch_row(i, j);
break;
}
}
try_switch_col(j);
for (int k = 0; k < am.length; k++) {
if (k != j)
xiao_yuan(j, k);
}
}
}
void show() {
for (int i = 0; i < am.length; i++) {
for (int j = 0; j < am[i].length; j++)
System.out.print(String.format("%3d", am[i][j]));
System.out.print(String.format("%6d", bm[i]));
System.out.println();
}
System.out.println("----");
for (int i = 0; i < 19; i++)
System.out.print(col[i] + " ");
System.out.println();
}
void test(int[] x) {
for (int k = 11; k >= 0; k--) {
int t1 = 0;
for (int i = 12; i < 19; i++)
t1 += am[k][i] * x[i];
int t = (bm[k] - t1) / am[k][k];
if (t < 1 || t > 19)
return; // 非法值
for (int i = k + 1; i < 19; i++)
if (t == x[i])
return; // 重复值
x[k] = t;
}
System.out.println("find: ");
int[] y = new int[19];
for (int i = 0; i < 19; i++)
y[col[i]] = x[i];
for (int i = 0; i < 19; i++)
System.out.print(y[i] + " ");
// for(int i=0; i<19; i++) System.out.print(x[i] + " ");
System.out.println();
}
// k: 当前要填充的位置
void f(int[] x, int k) {
if (k < 12) {
test(x);
return;
}
L1: for (int n = 1; n <= 19; n++) {
for (int i = k + 1; i < 19; i++)
if (x[i] == n)
continue L1;
x[k] = n;
f(x, k - 1);
if (k == 18)
System.out.println(".. " + n);
}
}
void search() {
int[] x = new int[19];
f(x, 18);
}
public static void main(String[] args) {
A a = new A();
a.init();
a.gauss();
a.show();
a.search();
}
}