题意:
给两个值,sum和head,按字典序输出所有满足的条件的5*5方格:
(1)最左上角的数位head
(2)每行、每列、两条对角线的和都等于sum
(3)每行、每列、两条对角线组成的五位数都是素数(从左到右,从上到下)
思路:
暴力搜索的样子。。。我解出来很慢,花了蛮多时间的
思路是:首先把期间的素数预处理出来,
先枚举第一行,再递归枚举最后一列,倒数第二列,倒数第三列,最后只剩下八个空,只需要枚举一个空,其余七个空都能填充
完成之后去看别人的做法,发现别人的做法更加无脑。。。
之所以先枚举第一行,是因为第一个数是确定的,再枚举最后一行,是因为最后一行有很多都可以被排除(因为最后一行的数都是每一行的末尾,不能有2,4,6,8,5出现)
我觉得比较好的枚举顺序是:第一行 -> 第一列 -> 最后一列-> 任意一条对角线 -> 剩余八个空格中的一个
总之,先枚举的一定是状态少的达到剪枝的目的,当然,用循环取消递归。。。
/*
TASK: prime3
ID: jasison2
LANG: C++
*/
/**
* @date 2014-04-18 18:42:54
* @author jasison
* @email jasison27@gmail.com
* @website http://www.jiangshan27.com
*/
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 100000;
bool notp[N];
vector<int>v[46][10];
int calc(int x){
int ret=0;
while(x){
ret+=x%10;
x/=10;
}
return ret;
}
void process(){
memset(notp,0,sizeof(notp));
int up=int(sqrt(N));
for(int i=2;i<=up;++i){
if(!notp[i]){
for(int j=i*i;j<N;j+=i){
notp[j]=1;
}
}
}
for(int i=10000;i<N;++i){
if(!notp[i]){
v[calc(i)][i/10000].push_back(i);
}
}
}
int sum,head,an;
int ma[5][5];
struct Ans{
int matrix[5][5];
bool operator<(const Ans &obj)const {
for(int i=0;i<5;++i){
for(int j=0;j<5;++j){
if(matrix[i][j]!=obj.matrix[i][j]){
return matrix[i][j]<obj.matrix[i][j];
}
}
}
return 0;
}
void output(){
for(int i=0;i<5;++i){
for(int j=0;j<5;++j){
printf("%d",matrix[i][j]);
}
puts("");
}
}
}ans[200];
bool judge(int r,int c,int x){
if(x<0||x>9){
return 0;
}
if(c==4 || r==4){
if(!(x&1) || x==5){
return 0;
}
}
if(r==0 || c==0){
if(x==0){
return 0;
}
}
return 1;
}
bool fill(bool row,int index,int x){
bool flag=1;
if(row){
for(int j=4;j>=0;--j){
ma[index][j]=x%10;
if(!judge(index,j,x%10)){
flag=0;
}
x/=10;
}
}else{
for(int i=4;i>=0;--i){
ma[i][index]=x%10;
if(!judge(i,index,x%10)){
flag=0;
}
x/=10;
}
}
return flag;
}
void pushAns(){
for(int i=0;i<5;++i){
for(int j=0;j<5;++j){
ans[an].matrix[i][j]=ma[i][j];
}
}
an++;
}
bool judge(bool row,int index){
int tot;
if(row){
tot=0;
for(int j=0;j<5;++j){
tot=10*tot+ma[index][j];
}
if(!binary_search(v[sum][ma[index][0]].begin(),v[sum][ma[index][0]].end(),tot)) {
return 0;
}
}else{
tot=0;
for(int i=0;i<5;++i){
tot=10*tot+ma[i][index];
}
if(!binary_search(v[sum][ma[0][index]].begin(),v[sum][ma[0][index]].end(),tot)) {
return 0;
}
}
return 1;
}
bool specialjudge(){
int tot=0;
for(int i=0;i<5;++i){
tot=10*tot+ma[i][i];
}
if(!binary_search(v[sum][ma[0][0]].begin(),v[sum][ma[0][0]].end(),tot)) {
return 0;
}
tot=0;
for(int i=0;i<5;++i){
tot=10*tot+ma[4-i][i];
}
if(!binary_search(v[sum][ma[4][0]].begin(),v[sum][ma[4][0]].end(),tot)) {
return 0;
}
return 1;
}
bool alljudge(){
return judge(false,0) &&
judge(false,1) &&
judge(true,1) &&
judge(true,2) &&
judge(true,3) &&
judge(true,4) &&
specialjudge();
}
void output(){
for(int i=0;i<5;++i){
for(int j=0;j<5;++j){
printf("%d",ma[i][j]);
}
puts("");
}
puts("");
}
void fillall(){
ma[1][1]=sum-ma[0][0]-ma[2][2]-ma[3][3]-ma[4][4];
if(!judge(1,1,ma[1][1])) return;
ma[1][0]=sum-ma[1][1]-ma[1][2]-ma[1][3]-ma[1][4];
if(!judge(1,0,ma[1][0])) return;
for(ma[4][0]=1;ma[4][0]<10;ma[4][0]+=2){
if(ma[4][0]==5) continue;
ma[3][1]=sum-ma[4][0]-ma[2][2]-ma[1][3]-ma[0][4];
if(!judge(3,1,ma[3][1])) continue;
ma[4][1]=sum-ma[4][0]-ma[4][2]-ma[4][3]-ma[4][4];
if(!judge(4,1,ma[4][1])) continue;
ma[3][0]=sum-ma[3][1]-ma[3][2]-ma[3][3]-ma[3][4];
if(!judge(3,0,ma[3][0])) continue;
ma[2][1]=sum-ma[0][1]-ma[1][1]-ma[3][1]-ma[4][1];
if(!judge(2,1,ma[2][1])) continue;
ma[2][0]=sum-ma[0][0]-ma[1][0]-ma[3][0]-ma[4][0];
if(!judge(2,0,ma[2][0])) continue;
if(alljudge()){
pushAns();
}
}
}
void dsolve(int c){
if(c==1){
fillall();
return;
}
for(int i=v[sum][ma[0][c]].size()-1;i>=0;--i){
if (fill(false,c,v[sum][ma[0][c]][i])){
dsolve(c-1);
}
}
}
void solve(){
an=0;
for(int i=v[sum][head].size()-1;i>=0;--i){
if (fill(true,0,v[sum][head][i])){
dsolve(4);
}
}
if(an==0){
puts("NONE");
}else{
sort(ans,ans+an);
for(int i=0;i<an;++i){
if(i!=0){
puts("");
}
ans[i].output();
}
}
}
int main() {
freopen("prime3.in","r",stdin);
freopen("prime3.out","w",stdout);
process();
while(scanf("%d%d",&sum,&head)!=EOF){
solve();
}
return 0;
}