质数阵
Time Limit:2000MSMemory Limit:30000KB
Total Submit:565Accepted:152
Description
在N*N的棋盘上(1<=N<=10)填入1,2,...N*N共N*N个数,使得任意两个相邻的数之和为素数.
例如,当N=2时,有
1 2
4 3
Input
每组测试数据一行,为一整数N(1<=N<=10)
Output
输出满足条件的最小序列的方案。
最小序列即将每一行连接起来组成一行,然后使前面的尽可能小,当第一个数字相同时则比较下面一个,依次类推。
比如当N=2时,序列为1 2 4 3,当无满足条件的方案时输出"no answer"。
Sample Input
2
1 2
4 3
题目分析:
思路同素数环,从上到下,从左到右依次枚举每个位置,依次枚举每个值,若此数尚未被使用,同时它与自己上方(当不为第一行)和左方的数(当不为第一列)的和均为质数时则保存路径后往下一层搜索,否则回溯到上一层。先预处理求出200内的质数,这样可以在o(1)内判断一个数是否为素数,将每个n的答案存到一个数组中,这样对有过的询问就可以不用再搜索。注意奇偶优化或者枚举质数和,否则会超时枚举质数进行优化:
#include <iostream>
#include <cstring>
using namespace std;
int a[202],prime[100]={},n,ans[11][11][11];
int map[11][11];
bool used[105],judge[12],success;
void dfs(int x,int y,int k){
int i;
if(success) return;
else if(x>k){
if(a[map[k][k]+map[k][k-1]] && a[map[k][k]+map[k-1][k]]){
success=true;
for(int i=1;i<=k;++i)
for(int j=1;j<=k;++j)
ans[i][j][k]=map[i][j];
}
}
else{
int tem;
if(y==1)
tem=map[x-1][1];
else tem=map[x][y-1];
for(i=lower_bound(prime,prime+46,tem)-prime;prime[i]-tem<=k*k;++i){
if(prime[i]>tem){
int t=prime[i]-tem;
if(!used[t]){
bool flag=true,tag=true;
if(x>1)
flag=a[t+map[x-1][y]];
if(y>1)
tag=a[t+map[x][y-1]];
if(flag && tag){
map[x][y]=t;
used[t]=true;
if(y!=k)
dfs(x,y+1,k);
else
dfs(x+1,1,k);
used[t]=false;
}
}
}
}
}
}
int main()
{
int i,j,k=0;
for(i=1;i<=200;++i)
a[i]=i;
i=2;
while(i<15){
if(a[i])
for(j=2;i*j<200;++j)
a[i*j]=0;
++i;
}
for(i=2;i<200;++i)
if(a[i])
prime[k++]=a[i];
n=k;
for(i=2;i<=10;++i){
memset(used,false,sizeof(used));
success=false;
map[1][1]=1;
used[1]=true;
dfs(1,2,i);
judge[i]=success;
}
int m;
while(cin>>m){
if(m==1)
cout<<"1"<<endl;
else{
if(!judge[m])
cout<<"no answer"<<endl;
else{
for(i=1;i<=m;++i){
for(j=1;j<=m;++j){
if(j>1) cout<<" ";
cout<<ans[i][j][m];
}
cout<<endl;
}
}
}
}
return 0;
}
奇偶优化:
#include <iostream>
#include <cstring>
using namespace std;
int a[202],prime[100]={},n,ans[11][11][11];
int map[11][11];
bool used[105],judge[12],success;
void dfs(int x,int y,int k){
int i;
if(success) return;
else if(x>k){
if(a[map[k][k]+map[k][k-1]] && a[map[k][k]+map[k-1][k]]){
success=true;
for(int i=1;i<=k;++i)
for(int j=1;j<=k;++j)
ans[i][j][k]=map[i][j];
}
}
else{
int tem;
if(y==1)
tem=map[x-1][y];
else tem=map[x][y-1];
if(tem&1) i=2;
else i=1;
for(;i<=k*k;i+=2){
if(!used[i]){
bool flag=true,tag=true;
if(x>1)
flag=a[i+map[x-1][y]];
if(y>1)
tag=a[i+map[x][y-1]];
if(flag && tag){
map[x][y]=i;
used[i]=true;
if(y!=k)
dfs(x,y+1,k);
else
dfs(x+1,1,k);
used[i]=false;
}
}
}
}
}
int main()
{
int i,j,k=0;
for(i=1;i<=200;++i)
a[i]=i;
i=2;
while(i<15){
if(a[i])
for(j=2;i*j<200;++j)
a[i*j]=0;
++i;
}
for(i=2;i<200;++i)
if(a[i])
prime[k++]=a[i];
n=k;
for(i=2;i<=10;++i){
memset(used,false,sizeof(used));
success=false;
map[1][1]=1;
used[1]=true;
dfs(1,2,i);
judge[i]=success;
}
int m;
while(cin>>m){
if(m==1)
cout<<"1"<<endl;
else{
if(!judge[m])
cout<<"no answer"<<endl;
else{
for(i=1;i<=m;++i){
for(j=1;j<=m;++j){
if(j>1) cout<<" ";
cout<<ans[i][j][m];
}
cout<<endl;
}
}
}
}
return 0;
}