P1549 [NOIP 1997 提高组] 棋盘问题
\[f(i) = \sum_{j=1}^{n^2} [i+j \in \mathbb{P}]
\]
\[\sum_{i=1}^{n^2} f(i) = \Theta(\frac{n^4}{\log n})
\]
搜索+剪枝,最优性剪枝:当和超过最优解是剪枝,改变搜索顺序:优先枚举第一行和第一列。
当 \(n\) 很小时足够枚举所有状态,当 \(n\) 很大时观察到合法的解非常少,可能只有唯一解,搜到直接退出大概率正确。
#include <bits/stdc++.h>
#define umap unordered_map
#define vint vector<int>
#define ll long long
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define ull unsigned long long
#define uint unsigned int
#define rg register
#define il inline
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define sqr(x) ((x)*(x))
using namespace std;
const int INF=0x3f3f3f3f;
inline int read(){
int w=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
w=(w<<1)+(w<<3)+(ch^48);
ch=getchar();
}
return w*f;
}
inline void write(int x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9) write(x/10);
putchar(x%10+'0');
}
clock_t st=clock();
bool is_prime(int x){
for(int i=2;i*i<=x;++i){
if(x%i==0) return 0;
}
return 1;
}
int a[20][20],n,vis[114514];
vint gg[114514];
vector<pii> order;
int ans[20][20],sum=INF;
auto get_choice(int x,int y){
set<int> res;
rep(i,1,n*n) if(!vis[i]) res.insert(i);
if(x!=1){
set<int> tmp;
for(int i:gg[a[x-1][y]]){
if(res.find(i)!=res.end()) tmp.insert(i);
}
res=tmp;
}
if(y!=1){
set<int> tmp;
for(int i:gg[a[x][y-1]]){
if(res.find(i)!=res.end()) tmp.insert(i);
}
res=tmp;
}
return res;
}
int cnt;
bool flag=0;
void dfs(int k,set<int> choice,int hang,int lie){
if(flag) return;
if(clock()-st>0.97*CLOCKS_PER_SEC) return;
if(hang+lie>sum) return;
if(k==n*n){
int tmp=0;
rep(i,1,n) tmp+=a[i][1]+a[1][i];
if(tmp<sum){
rep(i,1,n) rep(j,1,n) ans[i][j]=a[i][j];
sum=tmp;
if(n>=6) flag=1;
}
return;
}
for(auto i:choice){
if(vis[i]) continue;
auto [x,y]=order[k];
a[x][y]=i,vis[i]=1;
auto nxt=get_choice(order[k+1].first,order[k+1].second);
dfs(k+1,nxt,x==1?hang+a[x][y]:hang,y==1?lie+a[x][y]:lie);
vis[i]=0;
}
}
int main(){
#ifndef ONLINE_JUDGE
//freopen("in.txt","r",stdin);
#endif
cin>>n;
for(int i=1;i<=n*n;++i){
for(int j=1;j<=n*n;++j){
if(i!=j){
if(is_prime(i+j)) gg[i].push_back(j);
}
}
}
rep(i,1,n) order.push_back({1,i});
rep(i,2,n) order.push_back({i,1});
rep(i,2,n){
rep(j,2,n) order.push_back({i,j});
}
order.push_back({1,1});
// cout<<order.size()<<endl;
// for(int i=1;i<=n*n;++i){
// for(auto j:gg[i]) cout<<j<<" ";
// cout<<endl;
// }
// cout<<endl;
set<int> choice;
choice.insert(1);
dfs(0,choice,0,0);
if(sum==INF||n==1) puts("NO");
else{
rep(i,1,n){
rep(j,1,n){
cout<<ans[i][j]<<" ";
}
cout<<endl;
}
}
#ifndef ONLINE_JUDGE
fprintf(stderr,"%f\n",1.0*clock()/CLOCKS_PER_SEC);
#endif
return 0;
}

浙公网安备 33010602011771号