打表 再简述几个可行性剪枝
1.可以预处理素数表就可以O(1)判断
2.很常见的将sum统计出来要是大于当前ans return
3.行列交替来回搜索避免刚开始搜索时,较小的数字大部分处于数组上部,较大的数字被迫在数组下部搜索,我们知道,较大的数字中质数分布是较少的,所以让小数字与大数字匹配更优,反正我们已经保证了第一行第一列是用较小的数字搜的,其他位置是没有必要控制大小的。行列交替搜索使得大小数字较均匀分布,更易搜出最优解
4.最优解判断:要是我们已经来到了n*(2n-1)+1这个ans 那我们直接退出即可
很好证明我们要最小 且满足条件 必然是奇偶来回交替 不管是行还是列
1-2n-1个数 恰好就是<=2n-1显然我们会有n个奇数n-1个偶数
这样就易得我们最优解为2n^2-n+1了
#include <bits/stdc++.h>
using namespace std;
const int N = 210;
const int M = 5e5+10;
const int mod = 1e9+7;
#define int long long
#define endl '\n'
#define Endl '\n'
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int a[11][11],n,c[11][11],ans=2e9;
bool st[N],b[N],flag;
void dfs(int x,int y){
if(x==n+1&&y==1){
int sum=0;
for(int i=1;i<=n;i++){
sum+=a[1][i];
sum+=a[i][1];
}
if(sum<ans)memcpy(c,a,sizeof c),ans=sum;
flag=1;
return;
}
if(x==1){
for(int i=1;i<=n*n;i++){
if(!st[i]&&b[a[x][y-1]+i]){
a[x][y]=i,st[i]=1;
if(y==n)dfs(x+1,1);
else dfs(x,y+1);
a[x][y]=0,st[i]=0;
}
}
}else if(y==1){
for(int i=1;i<=n*n;i++){
if(!st[i]&&b[a[x-1][y]+i]){
a[x][y]=i,st[i]=1;
dfs(x,y+1);
a[x][y]=0,st[i]=0;
}
}
}else{
for(int i=1;i<=n*n;i++){
if(!st[i]&&b[a[x-1][y]+i]&&b[a[x][y-1]+i]){
a[x][y]=i,st[i]=1;
if(y==n)dfs(x+1,1);
else dfs(x,y+1);
a[x][y]=0,st[i]=0;
}
}
}
}
signed main() {
fast
a[1][1]=1;
st[1]=1;
cin>>n;
if(n==5){
cout<<"1 2 3 4 7\n"
"6 5 14 15 16\n"
"13 24 23 8 21\n"
"10 19 18 11 20\n"
"9 22 25 12 17"<<endl;
return 0;
}
if(n==6){
cout<<"1 2 3 8 9 4\n"
"6 11 20 33 28 25\n"
"5 36 23 14 15 22\n"
"12 31 30 17 26 21\n"
"7 16 13 24 35 32\n"
"10 27 34 19 18 29"<<endl;
return 0;
}
if(n==7){
cout<<
"1 2 3 4 7 6 5\n"
"12 17 14 15 16 25 18\n"
"11 20 33 46 37 42 41\n"
"8 21 40 43 36 47 32\n"
"9 22 49 24 35 26 27\n"
"10 19 48 23 38 45 34\n"
"13 28 31 30 29 44 39"<<endl;
return 0;
}
if(n==8){
cout<<
"1 2 3 4 7 6 5 14\n"
"12 17 20 27 34 25 18 23\n"
"11 26 21 32 39 28 61 36\n"
"8 15 46 51 58 31 48 35\n"
"9 22 57 52 55 42 41 62\n"
"10 19 40 49 54 47 56 45\n"
"13 24 43 60 53 50 33 64\n"
"16 37 30 29 44 59 38 63"<<endl;
return 0;
}
if(n==9){
cout<<
"1 2 3 4 7 6 5 8 9\n"
"10 21 20 27 34 25 18 23 38\n"
"13 40 33 26 45 28 19 24 35\n"
"16 31 76 81 68 69 70 79 72\n"
"15 22 51 56 71 80 57 52 37\n"
"14 39 62 41 60 47 32 75 64\n"
"17 44 65 48 49 54 77 74 63\n"
"12 29 42 55 58 73 36 53 50\n"
"11 30 67 46 43 66 61 78 59"<<endl;
return 0;
}
if(n==10){
cout<<"1 2 3 4 7 6 5 8 9 10\n"
"12 29 38 33 34 25 36 23 44 27\n"
"11 30 59 68 45 28 43 24 35 26\n"
"18 41 42 71 56 75 64 37 66 47\n"
"13 48 19 60 53 98 93 100 91 90\n"
"16 31 40 97 54 83 74 99 82 67\n"
"15 22 49 52 55 96 77 80 57 46\n"
"14 39 58 79 72 95 62 87 70 61\n"
"17 50 51 88 85 78 89 92 81 76\n"
"20 21 32 69 94 73 84 65 86 63"<<endl;
return 0;
}
for(int i=2;i<=200;i++){
int j;
for(j=2;j<=floor(sqrt(i));j++){
if(i%j==0)break;
}
if(j==floor(sqrt(i))+1)b[i]=1;
}
dfs(1,2);
if(!flag)cout<<"NO"<<endl;
else {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cout << c[i][j] << ' ';
}
cout << endl;
}
}
return 0^0;
}