In the square below, each row, each column and the two diagonals can be read as a five digit prime number. The rows are read from left to right. The columns are read from top to bottom. Both diagonals are read
from left to right.
+---+---+---+---+---+
| 1 | 1 | 3 | 5 | 1 |
+---+---+---+---+---+
| 3 | 3 | 2 | 0 | 3 |
+---+---+---+---+---+
| 3 | 0 | 3 | 2 | 3 |
+---+---+---+---+---+
| 1 | 4 | 0 | 3 | 3 |
+---+---+---+---+---+
| 3 | 3 | 3 | 1 | 1 |
+---+---+---+---+---+
- The prime numbers' digits must sum to the same number.
- The digit in the top left-hand corner of the square is pre-determined (1 in the example).
- A prime number may be used more than once in the same square.
- If there are several solutions, all must be presented (sorted in numerical order as if the 25 digits were all one long number).
- A five digit prime number cannot begin with a zero (e.g., 00003 is NOT a five digit prime number).
PROGRAM NAME: prime3
INPUT FORMAT
A single line with two space-separated integers: the sum of the digits and the digit in the upper left hand corner of the square.
SAMPLE INPUT (file prime3.in)
11 1
OUTPUT FORMAT
Five lines of five characters each for each solution found, where each line in turn consists of a five digit prime number. Print a blank line between solutions. If there are no prime squares for the input data,
output a single line containing "NONE".
SAMPLE OUTPUT (file prime3.out)
The above example has 3 solutions.
11351
14033
30323
53201
13313
11351
33203
30323
14033
33311
13313
13043
32303
50231
13331
题目分析:
使用dfs搜索。看似简单,写起来非常恶心。目测是我在usaco上代码量最长的程序。
枚举的时候注意顺序。
(1)先枚举第一行和第一列(因为左上角的数字已经给出,因此只需要枚举4个数字),下图中标“1”的地方表示已经枚举出来。
1 1 1 1 1
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
(2)再枚举副对角线:(第一个数字和最后一个数字已知,只需要枚举3个数字)。
1 1 1 1 1
1 0 0
1 0
1 0 1
0 0
1
1 0 0 0
1 0 0 0 0
(3)枚举主对角线:(第一个数字和第三个数字已知,只需要枚举3个数字):
1 1 1 1 1
1 1 0 1 0
1 0 1 0 0
1 1 0
1 0
1 0 0 0
1
(4)枚举第三行:(第一个数字和第三个数字已知,只需要枚举3个数字):
1 1 1 1 1
1 1 0 1 0
1 1 1
1 1
1 1 0 1 0
1 0 0 0 1
(5)枚举第三列:(第一个数字和第三个数字已知,只需要枚举3个数字):
1 1 1 1 1
1 1 1 1 0
1 1 1 1 1
1 1 1 1 0
1 0
1 0 1
(6)经过(1)~(5),可以发现,剩下的四个空的位置,已经可以推出(每一行每一列的和都是定值sum)。因此dfs到第六层的时候,这个矩阵就确定下来了。这个时候对其进行check,看是否满足题意(每行每列+对角线都是质数,每行每列+对角线的和都是定值sum)。
值得注意的是,我们可以发现(3)(4)(5)步骤非常神似,因此我们可以预处理一下,将那种 已知第1个和第3个数字,满足题设条件的剩余的三个数字的所有情况都存入到链表中(在我的代码中是thirdlist),同理第(1)步骤的情况存入firstlist,第(2)步骤的情况存入secondlist。
此外,还需要加一个剪枝操作:事实上进行完第(4)步骤后,就可以求得矩阵中(5,2)和(5,4)这两个位置的值,可以先进行一个check,如果不满足,则不继续进行第(5)步。
加上这个减枝后,最大样例可以在0.2秒通过。
分析
/*
ID: lisendo1
PROG: prime3
LANG: C++
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include