题意:有一个5*5的方阵,每行(从左至右)、每列(从上至下)和两条对角线(从左到右)上的5位数都是质数,且质数每位的数字之和一样。给定这个数字之和N以及方阵左上角的数M,求出所有的5*5方阵
解题思路:
- 求出所有符合条件的5位质数
- 按照上图,首先根据给定的左上角的数M来确定一条对角线上的数,满足条件的五位数在1中求出的集合中找,在图中以0来表示
- 在2的基础上用多重循环分别列举各位上的数,列举的顺序在上图中给出,其中带括号的意味着可以根据所在的行(列、对角线)的数字之和N推出
- 如果数字之和已经超过N,及时break掉该层循环,达到剪枝的目的
- 第一行(列)上的数不能为0,最后一行(列)上的数只能为1,3,7,9,这也是很重要的剪枝
- 确定一行(列、对角线)上所有的数之后,要看该数是否是质数。如果不是则continue该层循环,如果是则进入下层循环
- 在确定所有的数之后,还需要检测中间一列是否满足条件,如果满足则此5*5方阵是答案中的一个,存储下来
- 最后将存储下来的答案排序输出即可
代码:
/*
ID: zc.rene1
LANG: C
PROG: prime3
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
int N, M;
int digits[5];
int primes[90000][5];
int prime_num = 0;
int matrix[5][5];
int map[10][10][10][10][10];
int result[100][25];
int result_num = 0;
int IsPrime(void)
{
int sum = 0;
int i;
for (i=0; i<5; i++)
{
sum *= 10;
sum += digits[i];
}
for (i=2; i<=sqrt(sum); i++)
{
if (sum % i == 0)
{
return 0;
}
}
return 1;
}
void Check(void)
{
int i;
int sum = 0;
for (i=0; i<5; i++)
{
sum += digits[i];
}
if (sum == N)
{
if (IsPrime())
{
memcpy(primes[prime_num], digits, 5 * sizeof(int));
map[digits[0]][digits[1]][digits[2]][digits[3]][digits[4]] = prime_num;
prime_num++;
}
}
}
int DFS(int depth)
{
int i;
if (depth == 5)
{
Check();
return ;
}
for (i=0; i<=9; i++)
{
digits[depth] = i;
DFS(depth + 1);
}
}
void Search(void)
{
int i = 0, j;
int x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20;
while (primes[i][0] != M)
{
i++;
}
while (primes[i][0] == M)
{
/*diagonal*/
for (j=0; j<5; j++)
{
matrix[j][j] = primes[i][j];
}
/*1 2 3 (4)*/
for (x1=1; x1<=9; x1+=2)
{
if (x1 == 5)
{
continue;
}
if (x1 + matrix[2][2] > N)
{
break;
}
for (x2=1; x2<=9; x2+=2)
{
if (x2 == 5)
{
continue;
}
if (x1 + x2 + matrix[2][2] > N)
{
break;
}
for (x3=0; x3<=9; x3++)
{
x4 = N - (x1 + x2 + x3 + matrix[2][2]);
if (x4 < 0)
{
break;
}
if (map[x1][x3][matrix[2][2]][x4][x2] != -1)
{
matrix[4][0] = x1;
matrix[3][1] = x3;
matrix[1][3] = x4;
matrix[0][4] = x2;
/*5 6 (7)*/
for (x5=1; x5<=9; x5+=2)
{
if (x5 == 5)
{
continue;
}
if (x2 + x5 + matrix[4][4] > N)
{
break;
}
for (x6=1; x6<=9; x6+=2)
{
if (x6 == 5)
{
continue;
}
x7 = N - (x2 + x5 + x6 + matrix[4][4]);
if (x7 < 0)
{
break;
}
if (map[x2][x5][x7][x6][matrix[4][4]] != -1)
{
matrix[1][4] = x5;
matrix[3][4] = x6;
matrix[2][4] = x7;
/*8 9 (10)*/
for (x8=1; x8<=9; x8+=2)
{
if (x8 == 5)
{
continue;
}
if (x1 + x8 + matrix[4][4] > N)
{
break;
}
for (x9=1; x9<=9; x9+=2)
{
if (x9 == 5)
{
continue;
}
x10 = N - (x1 + x8 + x9 + matrix[4][4]);
if (x10 < 0)
{
break;
}
if (map[x1][x8][x10][x9][matrix[4][4]] != -1)
{
matrix[4][1] = x8;
matrix[4][3] = x9;
matrix[4][2] = x10;
/*11 (12)*/
for (x11=1; x11<=9; x11++)
{
x12 = N - (x11 + matrix[1][1] + x3 + x8);
if (x12 < 0)
{
break;
}
if (map[x11][matrix[1][1]][x12][x3][x8] != -1)
{
matrix[0][1] = x11;
matrix[2][1] = x12;
/*13 (14)*/
for (x13=1; x13<=9; x13++)
{
x14 = N - (x13 + matrix[1][1] + x4 + x5);
if (x14 < 0)
{
break;
}
if (map[x13][matrix[1][1]][x14][x4][x5] != -1)
{
matrix[1][0] = x13;
matrix[1][2] = x14;
/*15 (16) (17) (18) (19) (20)*/
for (x15=1; x15<=9; x15++)
{
x16 = N - (x15 + x4 + matrix[3][3] + x9);
if (x16 < 0)
{
break;
}
if (map[x15][x4][x16][matrix[3][3]][x9] != -1)
{
x17 = N - (matrix[0][0] + x11 + x15 + x2);
if (x17 < 0)
{
continue;
}
if (map[matrix[0][0]][x11][x17][x15][x2] != -1)
{
x18 = N - (x12 + matrix[2][2] + x16 + x7);
if (x18 < 0)
{
continue;
}
if (map[x18][x12][matrix[2][2]][x16][x7] != -1)
{
x19 = N - (matrix[0][0] + x13 + x18 + x1);
if (x19 < 0)
{
continue;
}
if (map[matrix[0][0]][x13][x18][x19][x1] != -1)
{
x20 = N - (x19 + x3 + matrix[3][3] + x6);
if (x20 < 0)
{
continue;
}
if (map[x19][x3][x20][matrix[3][3]][x6] != -1)
{
matrix[0][3] = x15;
matrix[2][3] = x16;
matrix[0][2] = x17;
matrix[2][0] = x18;
matrix[3][0] = x19;
matrix[3][2] = x20;
/*test if satisfied*/
if (map[x17][x14][matrix[2][2]][x20][x10] != -1)
{
memcpy(result[result_num], matrix, 25 * sizeof(int));
result_num++;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
i++;
}
}
int IsBigger(int a[25], int b[25])
{
int i;
for (i=0; i<25; i++)
{
if (a[i] < b[i])
{
return 0;
}
else if (a[i] > b[i])
{
return 1;
}
}
return 0;
}
void Sort(void)
{
int i, j;
int temp[25];
for (j=result_num-1; j>0; j--)
{
for (i=0; i<j; i++)
{
if (IsBigger(result[i], result[i + 1]))
{
memcpy(temp, result[i], 25 * sizeof(int));
memcpy(result[i], result[i+1], 25 * sizeof(int));
memcpy(result[i+1], temp, 25 * sizeof(int));
}
}
}
}
int main(void)
{
FILE *fin, *fout;
int i, j;
fin = fopen("prime3.in", "r");
fout = fopen("prime3.out", "w");
fscanf(fin, "%d %d", &N, &M);
memset(map, -1, 100000 * sizeof(int));
for (i=1; i<=9; i++)
{
digits[0] = i;
DFS(1);
}
memset(matrix, -1, 25 * sizeof(int));
Search();
Sort();
for (i=0; i<result_num; i++)
{
for (j=0; j<25; j++)
{
fprintf(fout, "%d", result[i][j]);
if (j % 5 == 4)
{
fprintf(fout, "\n");
}
}
if (i != result_num -1)
{
fprintf(fout, "\n");
}
}
if (result_num == 0)
{
fprintf(fout, "NONE\n");
}
return 0;
}