noip1997提高组 填数字

 

问题描述

noip1997提高组 填数字_第1张图片

  如果有多组解,则输出字典序最小的一组。如果无解,输出NO。

输入格式
   第一行一个数n
输出格式
   无解输出NO,否则输出n行每行n个数表示字典序最小的方案。
样例输入
2
样例输出
1 2
4 3
数据规模和约定
  1<=n<=10
筛法处理素数表,然后深搜
看了人家的代码,好久才想通,不要笑我的智商低。
 

代码:

#include <cstdio>
#include <cstdlib>
#define maxn 100
int n, s, a[20][20];
bool flag[maxn*2+10], f[maxn+10];
void operate_prime() {
    int i, j, k;
    for(i = 2; i <= 200; i++)
        if(!flag[i]) for(j = 2*i; j <= 200; j += i)
            flag[j] = 1;
}
void write() {
    int i, j, k;
    for(i = 1; i <= n; i++) {
        for(j = 1; j < n; j++)
            printf("%d ", a[i][j]);
            printf("%d\n", a[i][n]);
        }
}
inline bool ok(int x, int y, int k) {
    if(f[k]) return 0;
    if(x-1>0 && flag[a[x-1][y]+k]) return 0;
    if(y-1>0 && flag[a[x][y-1]+k]) return 0;
    return 1;
}
void dfs(int x, int y) {
    if(x==n && y==n) {
        write();
        exit(0);
    }
    if(y+1 <=n) {
        for(int i = 2; i <= s; i++)
            if(ok(x, y+1, i)) {
                a[x][y+1] = i;
                f[i] = 1;
                dfs(x, y+1);
                f[i] = 0;
            }
    }
    else for(int i = 2; i <= s; i++)
                if(ok(x+1, 1, i)) {
                    a[x+1][1] = i;
                    f[i] = 1;
                    dfs(x+1, 1);
                    f[i] = 0;
                }
}
int main() {
    operate_prime();
    scanf("%d", &n);
    s = n*n;
    a[1][1] = 1; f[1] = 1;
    dfs(1, 1);
    printf("NO");
    return 0;
}

你可能感兴趣的:(noip1997提高组 填数字)