luogu P1549 棋盘问题(2) 题解

题目描述

在\(N * N\)的棋盘上\((1≤N≤10)\),填入\(1,2,…,N^2\)共\(N^2\)个数,使得任意两个相邻的数之和为素数。

例如:当\(N=2\)时,有:

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

\(1+2,1+4,4+3,2+3\)

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

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

输入输出格式

输入格式:

一个数\(N\)

输出格式:

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

输入输出样例

输入样例#1:

1

输出样例#1:

NO

输入样例#2:

2

输出样例#2:

1 2

4 3

思路

看这数据这么小\((1≤N≤10)\),所以可以dfs。

但是dfs直接跑一下一定是不行的。所以,可以发现题面的要求:输出第一行、第一列之和为最小的排列方案。

那么怎样使它最小呢?

很简单,只要在第一行、第一列dfs的枚举时,\(i\)枚举顺序为\(1~n^2\),而不是第一行、第一列的其他数字则要取最大值,即枚举顺序为\(n^2~1\)(down to)。

然后就是dfs了啊。。。

素数怎么判断呢??

预处理一下200之内的素数,然后用桶判断一下就好了呀。

ps:素数判断可以直接只判断dfs的左、上之和(已经搜索了的数)与之和是不是素数就好了。

下附代码:

  1. #include<algorithm>
  2. #include<bitset>
  3. #include<complex>
  4. #include<deque>
  5. #include<exception>
  6. #include<fstream>
  7. #include<functional>
  8. #include<iomanip>
  9. #include<ios>
  10. #include<iosfwd>
  11. #include<iostream>
  12. #include<istream>
  13. #include<iterator>
  14. #include<limits>
  15. #include<list>
  16. #include<locale>
  17. #include<map>
  18. #include<memory>
  19. #include<new>
  20. #include<numeric>
  21. #include<ostream>
  22. #include<queue>
  23. #include<set>
  24. #include<sstream>
  25. #include<stack>
  26. #include<stdexcept>
  27. #include<streambuf>
  28. #include<string>
  29. #include<typeinfo>
  30. #include<utility>
  31. #include<valarray>
  32. #include<vector>
  33. #include<cstring>
  34. #include<cmath>
  35. #define ll long long
  36. #define eps 1e-4
  37. using namespace std;
  38. //priority_queue<int,vector<int>,greater<int> > q1;
  39. //priority_queue<int> q2;
  40. //set<int> s;
  41. //list<int> l;
  42. //map<int> mp;
  43. inline int read(){
  44. int ret=0,f=1;char ch=getchar();
  45. while (ch<'0'||ch>'9') {if (ch=='-') f=-f;ch=getchar();}
  46. while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
  47. return ret*f;
  48. }
  49. inline void write(int zx){
  50. if(zx<0){zx=-zx;putchar('-');}
  51. if(zx<10) putchar(zx+'0');
  52. else{
  53. write(zx/10);
  54. putchar(zx%10+'0');
  55. }
  56. }
  57. int n;
  58. int f[15][15],ans;
  59. int prime[500];
  60. bool used[500];
  61. bool check(int zx){
  62. for(int i=2;i<=sqrt(zx);i++)
  63. if(zx%i==0) return 0;
  64. return 1;
  65. }
  66. void print(){
  67. for(int i=1;i<=n;i++){
  68. for(int j=1;j<=n;j++){
  69. write(f[i][j]);putchar(' ');
  70. }
  71. putchar('\n');
  72. }
  73. }
  74. void dfs(int x,int y){
  75. if(x==n&&y==n+1){
  76. ans=1;
  77. print();
  78. exit(0);
  79. }
  80. if(f[x][y]!=0) return ;
  81. if(y==n+1){
  82. dfs(x+1,1);
  83. return ;
  84. }
  85. int from=-1;
  86. if(x==1||y==1){
  87. for(int i=2;i<=n*n;i++){
  88. if(used[i]==1) continue ;
  89. if(x==1&&prime[f[x][y-1]+i]==0) continue ;
  90. if(y==1&&prime[f[x-1][y]+i]==0) continue ;
  91. f[x][y]=i;used[i]=1;
  92. dfs(x,y+1);
  93. f[x][y]=0;used[i]=0;
  94. }
  95. }else{
  96. for(int i=n*n;i>=2;i--){
  97. if(used[i]==1) continue ;
  98. if(prime[f[x][y-1]+i]==0) continue ;
  99. if(prime[f[x-1][y]+i]==0) continue ;
  100. f[x][y]=i;used[i]=1;
  101. dfs(x,y+1);
  102. f[x][y]=0;used[i]=0;
  103. }
  104. }
  105. }
  106. int main(){
  107. n=read();
  108. if(n==1){
  109. puts("NO");
  110. return 0;
  111. }
  112. for(int i=2;i<=500;i++)
  113. if(check(i)==1) prime[i]=1;
  114. f[1][1]=1;used[1]=1;
  115. dfs(1,2);
  116. puts("NO");
  117. return 0;
  118. }

luogu P1549 棋盘问题(2) 题解的更多相关文章

  1. Luogu P1549 棋盘问题(2)

    题意 在N×N的棋盘上(1≤N≤10),填入1,2,-,N^2,共N^2个数,使得任意两个相邻的数之和为素数. 思路 先线性筛(非标准版),然后用a数组记录以i为下标的数是不是质数(就是标记数组),然 ...

  2. luogu P1126 机器人搬重物 题解

    luogu P1126 机器人搬重物 题解 题目描述 机器人移动学会(\(RMI\))现在正尝试用机器人搬运物品.机器人的形状是一个直径\(1.6\)米的球.在试验阶段,机器人被用于在一个储藏室中搬运 ...

  3. luogu 1169 棋盘制作(单调栈/悬线)

    luogu 1169 棋盘制作(单调栈/悬线) 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应 ...

  4. 洛谷P1549 棋盘问题(2)

    P1549 棋盘问题(2) 题目描述 在N*N的棋盘上(1≤N≤10),填入1,2,…,N*N共N*N个数,使得任意两个相邻的数之和为素数. 例如:当N=2时,有: 其相邻数的和为素数的有: 1+2, ...

  5. 洛谷——P1549 棋盘问题(2)

    P1549 棋盘问题(2) 搜索||打表 #include<cstdio> #include<cstring> #include<iostream> #includ ...

  6. 【luogu P2491 [SDOI2011]消防】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2491 题外话: OI一共只有三种题--会的题,不会的题,二分题. 题解: step 1 求树的直径,把树的直 ...

  7. 【luogu P1040 加分二叉树】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1040 今天考试考了一个区间DP...没错就是这个... 太蒟了真是连区间DP都不会...看了看题解也看不懂, ...

  8. Luogu P1351 联合权值 题解

    这是一个不错的树形结构的题,由于本蒟蒻不会推什么神奇的公式其实是懒得推...,所以很愉快的发现其实只需要两个点之间的关系为祖父和儿子.或者是兄弟即可. 然后问题就变得很简单了,只需要做一个正常的DFS ...

  9. 【luogu P1850 换教室】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1850 难的不在状态上,难在转移方程. (话说方程写错居然还有84分= =) #include <cst ...

随机推荐

  1. mysql四-1:单表查询

    一 单表查询的语法 SELECT 字段1,字段2... FROM 表名 WHERE 条件 GROUP BY field HAVING 筛选 ORDER BY field LIMIT 限制条数 二 关键 ...

  2. Python多线程、进程、协程

    本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者 ...

  3. Linux I/O缓冲

    1:两类I/O函数的缓冲机制 1.1 系统调用(System call) 这类代表就是read/write等系统函数,它们是不带缓冲的,这里的缓冲指的是进程缓冲,在内核到磁盘之间还是有内核缓冲的. 1 ...

  4. Google protocol buffer的配置和使用(Linux&&Windows)

    最近自己的服务器做到序列化这一步了,在网上看了下,序列化的工具有boost 和google的protocol buffer, protocol buffer的效率和使用程度更高效一些,就自己琢磨下把他 ...

  5. bzoj 2795 [Poi2012]A Horrible Poem hash+数论

    2795: [Poi2012]A Horrible Poem Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 640  Solved: 322[Subm ...

  6. Java 8 Stream 用法

    一.Stream是什么 Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator.原始版本的 Iterator,用户只能显式地一个一个遍历元 ...

  7. 使用RVM轻松部署Ruby环境

    Ruby用得不多,但发现有业务需要部署指定的版本和插件.起初找了一些Fedora的src.rpm重新打包,发现依赖问题比较多,最终还是费劲的把el6的包编出来了. 不巧今天又有业务要求el5的包,原本 ...

  8. CF544 C 背包 DP

    n个人写m行代码,第i人写一行代码有a[i]个bug,问总bug数不超过b的不同方案数. 其实就是个背包,dp[i][j][k]代表前i个人写了j行代码用了k个bug限度,然后随便转移一下就好了 /* ...

  9. Java--图片浏览器

    功能:启动后选择打开文件,可以打开图片进行浏览. v 1.0 :支持上一张 下一张功能.(欠缺,窗口大小未随着图片大小而改变) import java.awt.BorderLayout; import ...

  10. Web 开发者易犯的5大严重错误

    无论你是编程高手,还是技术爱好者,在进行Web开发过程中,总避免不了犯各种各样的错误. 犯了错误,可以改正.但如果犯了某些错误,则会带来重大损失.遗憾.令人惊讶的是,这些错误往往是最普通,最容易避免. ...