搜索题目,状态很多,需要优化:
1.优化搜索顺序:先确定对角线,因为对角线对行列的影响最大。然后每次选取已确定数字个数最多的行列进行枚举,这样最省时间
2.合理设计数据结构:假设我们需要迅速查找到第一位和第五位分别为1,3的素数集合,该如何处理?预处理是搜索问题优化的好方法,可以在搜索前将各种需要枚举的素数集合分别存起来,这样速度将会快很多
3.如果某行或者某列已经有四个数确定了,那么第五个数可以直接算出来,如果它在0到9之间并且五个数组成起来是素数的话,那么就是符合条件的
下面图示解释了枚举顺序
processing order
03332
71?28
64156
72?18
24?51
错误总结:
1.写程序的时候忘记首位不能为0的要求了,所以,对于比较长的程序,最好列一下大纲,或者把关键步骤写出来,这样不容易错
2.边界问题。计算机处理的数据一般都有上下界,所以边界要时刻考虑,负数不能作下标
3.排序出错。对关键字是数字串的数组排序,很容易出错,compare时要注意如果当前可以比较出大小,要立即返回
- /*
- PROG: prime3
- LANG: C++
- ID: heben991
- */
- #include <iostream>
- #include <algorithm>
- using namespace std;
- const int n = 5, N = 100010, PN = 200, R = 10;
- int p[N], p1[R][PN*R], p3[R][PN*R],
- p15[R][R][PN], p124[R][R][R][PN],
- p234[R][R][R][PN], p135[R][R][R][PN];
- int sum;
- bool del[N];
- char a[n+1][n+1];
- struct data
- {
- char a[n+1][n+1];
- }ans[PN*PN], *out[PN*PN];
- int ans_num;
- bool cmp(const data *x, const data *y)
- {
- int i, j;
- for(i = 1; i <= n; ++i)
- for(j = 1; j <= n; ++j)
- {
- if(x->a[i][j] < y->a[i][j]) return true;
- if(x->a[i][j] > y->a[i][j]) return false; // don't forget this
- }
- return false;
- }
- void seperate(int x, char *num)
- {
- int i, j;
- for(i = n; i >= 1; --i)
- {
- num[i] = x%10;
- x /= 10;
- }
- }
- void get_prime()
- {
- int i, j;
- char num[n+1];
- for(i = 2; i < N; ++i)
- {
- if(!del[i])
- {
- p[++p[0]] = i;
- if(i >= 10000)
- {
- seperate(i, num);
- if(num[1]==1 && num[5]==2)
- {
- printf("%d/n", i);
- for(j = 1; j <= n; ++j) printf("%d ", num[j]);
- exit(0);
- }
- int t=0;
- bool zero=false;
- for(j = 1; j <= n; ++j)
- {
- t += num[j];
- if(num[j]==0) zero=1;
- }
- if(t == sum)
- {
- p1[num[1]][ ++p1[num[1]][0] ] = i;
- p3[num[3]][ ++p3[num[3]][0] ] = i;
- if(!zero) p15[num[1]][num[5]][ ++p15[num[1]][num[5]][0] ] = i;
- // zero!!
- p124[num[1]][num[2]][num[4]][ ++p124[num[1]][num[2]][num[4]][0] ] = i;
- p234[num[2]][num[3]][num[4]][ ++p234[num[2]][num[3]][num[4]][0] ] = i;
- p135[num[1]][num[3]][num[5]][ ++p135[num[1]][num[3]][num[5]][0] ] = i;
- }
- }
- }
- for(j = 1; j <= p[0] && p[j]*i < N; ++j)
- {
- del[p[j]*i] = true;
- if(i%p[j]==0) break;
- }
- }
- }
- void update()
- {
- memcpy(ans[++ans_num].a, a, sizeof(a));
- }
- bool fail_row(int row)
- {
- int i, x=0, t=0;
- for(i = 1; i <= n; ++i)
- {
- x *= 10;
- x += a[row][i];
- t += a[row][i];
- }
- return t!=sum || del[x];
- }
- bool fail_col(int col)
- {
- int i, x=0, t=0;
- for(i = 1; i <= n; ++i)
- {
- x *= 10;
- x += a[i][col];
- t += a[i][col];
- }
- return t!=sum || del[x];
- }
- /*
- process order
- 03332
- 71?28
- 64156
- 72?18
- 24?51
- the set of prime
- p1
- p3
- p15
- p124
- p234
- p135
- */
- int main()
- {
- int i, j, k, d1, d2, r1, c2, c4, r3, c1, c5;
- int s[3];
- char num[n+1];
- freopen("prime3.in","r",stdin);
- freopen("prime3.out","w",stdout);
- scanf("%d%d", &sum, &a[1][1]);
- get_prime();
- for(d1 = 1; d1 <= p1[a[1][1]][0]; ++d1)
- {
- seperate(p1[a[1][1]][d1], num);
- for(i = 2; i <= n; ++i)
- {
- a[i][i] = num[i];
- }
- for(d2 = 1; d2 <= p3[a[3][3]][0]; ++d2)
- {
- seperate(p3[a[3][3]][d2], num);
- for(i = 1; i <= n; ++i)
- {
- a[n-i+1][i] = num[i];
- }
- for(r1 = 1; r1 <= p15[a[1][1]][a[1][n]][0]; ++r1)
- {
- seperate(p15[a[1][1]][a[1][n]][r1], num);
- for(i = 2; i < n; ++i)
- {
- a[1][i] = num[i];
- }
- for(c2 = 1; c2 <= p124[a[1][2]][a[2][2]][a[4][2]][0]; ++c2)
- {
- seperate(p124[a[1][2]][a[2][2]][a[4][2]][c2], num);
- a[3][2] = num[3], a[5][2] = num[5];
- for(c4 = 1; c4 <= p124[a[1][4]][a[2][4]][a[4][4]][0]; ++c4)
- {
- seperate( p124[a[1][4]][a[2][4]][a[4][4]][c4], num);
- a[3][4] = num[3], a[5][4] = num[5];
- for(r3 = 1; r3 <= p234[a[3][2]][a[3][3]][a[3][4]][0]; ++r3)
- {
- seperate(p234[a[3][2]][a[3][3]][a[3][4]][r3], num);
- a[3][1] = num[1], a[3][5] = num[5];
- for(c1 = 1; c1 <= p135[a[1][1]][a[3][1]][a[5][1]][0]; ++c1)
- {
- seperate(p135[a[1][1]][a[3][1]][a[5][1]][c1], num);
- if(num[2]==0 || num[4]==0) continue;
- a[2][1] = num[2], a[4][1] = num[4];
- for(c5 = 1; c5 <= p135[a[1][5]][a[3][5]][a[5][5]][0]; ++c5)
- {
- seperate( p135[a[1][5]][a[3][5]][a[5][5]][c5], num);
- a[2][5] = num[2], a[4][5] = num[4];
- a[2][3] = sum - (a[2][1]+a[2][2]+a[2][4]+a[2][5]);
- if(a[2][3]<0 || a[2][3]>9 || fail_row(2)) continue;
- // 0<=a[2][i]<=9 && sum(a[2])==sum && prime(a[2])
- a[4][3] = sum - (a[4][1]+a[4][2]+a[4][4]+a[4][5]);
- if(a[4][3]<0 || a[4][3]>9 || fail_row(4)) continue;
- a[5][3] = sum - (a[1][3]+a[2][3]+a[3][3]+a[4][3]);
- if(a[5][3]<0 || a[5][3]>9 || fail_col(3) || fail_row(5)) continue;
- update();
- }
- }
- }
- }
- }
- }
- }
- }
- for(i = 1; i <= ans_num; ++i)
- {
- out[i] = ans+i;
- }
- sort(out+1, out+ans_num+1, cmp);
- for(i = 1; i <= ans_num; ++i)
- {
- for(j = 1; j <= n; ++j)
- {
- for(k = 1; k <= n; ++k)
- {
- printf("%d", out[i]->a[j][k]);
- }
- putchar('/n');
- }
- if(i!=ans_num) putchar('/n');
- }
- return 0;
- }