[Noip1997] 棋盘问题(2)

题目描述

N×NN \times NN×N的棋盘上(1≤N≤10)(1≤N≤10)(1N10),填入1,2,…,N21,2,…,N^21,2,,N2共N2N^2N2个数,使得任意两个相邻的数之和为素数。

例如:当N=2N=2N=2时,有:

其相邻数的和为素数的有:

1+2,1+4,4+3,2+31+2,1+4,4+3,2+31+2,1+4,4+3,2+3

N=4N=4N=4时,一种可以填写的方案如下:

在这里我们约定:左上角的格子里必须填数字111。

输入输出格式

输入格式:

一个数NNN

输出格式:

如有多种解,则输出第一行、第一列之和为最小的排列方案;若无解,则输出“NO”。

输入输出样例

输入样例#1: 复制
1
输出样例#1: 复制
NO
输入样例#2: 复制
2

输出样例#2: 复制

1 2




一开始没看到第一行和第一列的和最小,一直以为只用第一列的和最小...
其实都差不多...
就是正常的搜索, 加上一维判断是不是第一列第一行搜完了。
我采取的策略是先搜第一行第一列,然后从(2, 2)点开始搜索。


 
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define reg register
inline int read() {
    int res=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res;
}

int n;
bool is[105*2];
int use[105];
int a[15][15];

inline void dfs(int x, int y, int end, int beg)
{
    //printf("%d %d\n", x, y);
    if (end) {
        for (reg int i = 1 ; i <= n ; i ++, puts(""))
            for (reg int j = 1 ; j <= n ; j ++)
                printf("%d ", a[i][j]);
        exit(0);
    }
    bool flag = 0;
    for (reg int i = 2 ; i <= n * n ; i ++)
    {
        if (use[i]) continue;
        if ((x == 1 or is[i+a[x-1][y]]) and (y == 1 or is[i+a[x][y-1]]))
        {
            int x1 = x, y1 = y + 1;
            if (beg) {
                if (x == 1 and y >= 2) x1 = 1, y1 = y + 1;
                if (y == 1 and x >= 2) x1 = x + 1, y1 = 1;
                if (x == 1 and y == n) x1 = 2, y1 = 1;
            }
            flag = 1;
            int tmp = 0, tmp2 = beg;
            if (x == n and y == n) tmp = 1;
            if (x == n and y == 1) tmp2 = 0, x1 = 2, y1 = 2;
            if (!beg and y == n and x != n) x1 = x + 1, y1 = 2;
            a[x][y] = i;
            use[i] = 1;
            dfs(x1, y1, tmp, tmp2);
            use[i] = 0;
            a[x][y] = 0;
        }
    }
    if (!flag) return ;
}

int main()
{
    n = read();
    if (n == 1) return puts("NO"), 0;
    for (reg int i = 2 ; i <= n * n * 2 ; i ++)
    {
        for (reg int j = 2 ; j * j <= i ; j ++)
            if (i % j == 0) {is[i] = 0;goto End;}
        is[i] = 1;
        End:;
    }
    a[1][1] = 1;
    use[1] = 1;
    dfs(1, 2, 0, 1);
    puts("NO");
    return 0;
}

 

 
posted @ 2018-09-01 09:03  zZhBr  阅读(520)  评论(0编辑  收藏  举报