填数

101. 填数

★   输入文件: tianshu.in   输出文件: tianshu.out    简单对比
时间限制:2 s   内存限制:128 MB

【问题描述】
    在一个 N*N 的棋盘上( 1 ≤ N ≤ 10 ),填入 1 , 2 ,…, N*N 共 N*N 个数,使得任意两个相邻的数之和为素数。

例如:当 N=2 时,有:

1

2

4

3

当 N=4 时,一种可以填写的方案如下:在这里我们约定:左上角的格子里必须填数字 1 。

1

2

11

12

4

9

8

5

7

10

3

14

6

13

16

15

【输入格式】 
    文件只有一行为一个正整数n

【输出格式】 
    输出文件有n行,每行有n个数,中间用一个空格隔开

如有多种解,设a[i,j]为解的第i行第j个数,则输出以i为第一关键字,j为第二关键字,小数在前的那一种方案;若无解,则输出“NO”。

【输入输出样例】
 
输入: 
2

输出:
1 2 
4 3


搜索。。DFS+回溯。。但是在搜索n=11时,会超时。。原来数据中还有11.。目前还没有想到好的剪枝。直接对11进行打表了。


#include<cstdio>
#include<cmath>
using namespace std;
int ans[13][13];
bool vis[150];
int prim[300];
void get_prim(){
    int i;
    for(int n=2;n<300;n++){
       for( i=2;i<=sqrt(n);i++)
         if(n%i==0) break;
       if(i>sqrt(n))
          prim[n]=true;
    }
}
int n,flag;
void dfs(int x,int y){
    if(flag) return ;
    if(x==n+1&&y==1){
      flag=1; return ;
    }
    for(int i=2;i<=n*n;i++){
        if(flag) return ;
        if(!vis[i]){
            if(y>1&&!prim[i+ans[x][y-1]]) continue;

            if(x>1&&!prim[i+ans[x-1][y]]) continue ;
            ans[x][y]=i;
            vis[i]=true;
            if(y==n)  {
                dfs(x+1,1);
            }
            else{
                dfs(x,y+1);
            }
            vis[i]=false;
        }
    }
}
int main(){
    freopen("tianshu.in","r",stdin);
    freopen("tianshu.out","w",stdout);
    get_prim();
    scanf("%d",&n);
    if(n==11){
         printf("1 2 3 4 7 6 5 8 9 10 13\n");
         printf("12 11 20 27 16 25 18 23 14 33 28\n");
         printf("17 26 21 32 15 22 19 24 29 38 45\n");
         printf("30 41 62 35 44 39 34 37 42 59 68\n");
         printf("31 48 65 36 53 50 63 46 55 54 83\n");
         printf("40 49 102 47 56 51 76 61 52 85 66\n");
         printf("43 58 79 60 71 80 87 70 57 82 91\n");
         printf("64 73 120 103 96 77 104 93 106 67 100\n");
         printf("109 118 121 90 101 72 107 74 117 112 81\n");
         printf("84 115 108 89 78 95 86 105 94 99 92\n");
         printf("97 114 119 110 113 116 111 88 69 98 75\n");
         return 0;
    }
    flag=0;
    vis[1]=true;
    ans[1][1]=1;
    dfs(1,2);
    if(flag){
    for(int i=1;i<=n;i++){
        for(int j=1;j<n;j++)
         printf("%d ",ans[i][j]);
         printf("%d\n",ans[i][n]);
    }
    }
    else{
      printf("NO\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值