题目传送门

1 #include<bits/stdc++.h>
2 using namespace std;
3 int n,f[15][15];
4 bool prime[205],use[105];
5 bool check(int x) {
6 for(int i=2;i<=sqrt(x);i++)
7 if(x % i==0) return 0;
8 return 1;
9 }
10 void print() {
11 for(int i=1;i<=n;i++){
12 for(int j=1;j<n;j++)
13 printf("%d ",f[i][j]);
14 printf("%d
",f[i][n]);
15 }
16 exit(0);
17 }
18
19 void dfs(int x,int y) { //x为行,y为列
20 if(x==n&&y==n+1) print();
21 if(y==n+1) {dfs(x+1,1); return ;}
22 if(x==1||y==1)
23 for(int i=2;i<=n*n;i++) {
24 if(use[i]) continue;
25 if(x==1&&!prime[f[x][y-1]+i]) continue;
26 if(y==1&&!prime[f[x-1][y]+i]) continue;
27 f[x][y]=i; use[i]=1;
28 dfs(x,y+1);
29 f[x][y]=0; use[i]=0;
30 }
31 else for(int i=n*n;i>=2;i--) {
32 if(use[i]) continue;
33 if(!prime[f[x][y-1]+i]) continue;
34 if(!prime[f[x-1][y]+i]) continue;
35 f[x][y]=i; use[i]=1;
36 dfs(x,y+1);
37 f[x][y]=0; use[i]=0;
38 }
39 }
40
41 int main() {
42 scanf("%d",&n);
43 if(n==1) {printf("NO"); return 0;}
44 for(int i=2;i<=200;i++) //预处理200以内的素数
45 if(check(i)) prime[i]=1;
46 f[1][1]=1; use[1]=1; //左上角的格子里必须填数字1
47 dfs(1,2);
48 printf("NO");
49 }
50 /*
51 #DFS#
52 题面要求:输出第一行、第一列之和为最小的排列方案。
53 怎样使它最小?
54 ANS:在第一行、第一列数字dfs的枚举时,i枚举顺序为1~n^2。(尽量取小)
55 而不是第一行、第一列的其他数字枚举时,i枚举顺序为n^2~1。(尽量取大)
56 PS:素数判断可以只判断左、上(已经搜索过的数)与当前和是不是素数。
57 */
思路来自同校DALAO的博客。