『P1549』棋盘问题

题目传送门

 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\n",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博客

posted @ 2018-12-16 11:51  YeLingqi  阅读(187)  评论(0编辑  收藏  举报