usaco 4.3 Letter Game 搜索

 搜索题目,状态很多,需要优化:
1.优化搜索顺序:先确定对角线,因为对角线对行列的影响最大。然后每次选取已确定数字个数最多的行列进行枚举,这样最省时间
2.合理设计数据结构:假设我们需要迅速查找到第一位和第五位分别为1,3的素数集合,该如何处理?预处理是搜索问题优化的好方法,可以在搜索前将各种需要枚举的素数集合分别存起来,这样速度将会快很多
3.如果某行或者某列已经有四个数确定了,那么第五个数可以直接算出来,如果它在0到9之间并且五个数组成起来是素数的话,那么就是符合条件的

下面图示解释了枚举顺序
processing order
03332
71?28
64156
72?18
24?51

 

错误总结:
1.写程序的时候忘记首位不能为0的要求了,所以,对于比较长的程序,最好列一下大纲,或者把关键步骤写出来,这样不容易错
2.边界问题。计算机处理的数据一般都有上下界,所以边界要时刻考虑,负数不能作下标
3.排序出错。对关键字是数字串的数组排序,很容易出错,compare时要注意如果当前可以比较出大小,要立即返回

 

  1. /*
  2. PROG: prime3
  3. LANG: C++
  4. ID: heben991
  5. */
  6. #include <iostream>
  7. #include <algorithm>
  8. using namespace std;
  9. const int n = 5, N = 100010, PN = 200, R = 10;
  10. int p[N], p1[R][PN*R], p3[R][PN*R],
  11.     p15[R][R][PN], p124[R][R][R][PN],
  12.     p234[R][R][R][PN], p135[R][R][R][PN];
  13. int sum;
  14. bool del[N];
  15. char a[n+1][n+1];
  16. struct data
  17. {
  18.     char a[n+1][n+1];
  19. }ans[PN*PN], *out[PN*PN];
  20. int ans_num;
  21. bool cmp(const data *x, const data *y)
  22. {
  23.     int i, j;
  24.     for(i = 1; i <= n; ++i)
  25.         for(j = 1; j <= n; ++j)
  26.         {
  27.             if(x->a[i][j] < y->a[i][j]) return true;
  28.             if(x->a[i][j] > y->a[i][j]) return false// don't forget this
  29.         }
  30.     return false;
  31. }
  32. void seperate(int x, char *num)
  33. {
  34.     int i, j;
  35.     for(i = n; i >= 1; --i)
  36.     {
  37.         num[i] = x%10;
  38.         x /= 10;
  39.     }
  40. }
  41. void get_prime()
  42. {
  43.     int i, j;
  44.     char num[n+1];
  45.     for(i = 2; i < N; ++i)
  46.     {
  47.         if(!del[i])
  48.         {
  49.             p[++p[0]] = i;
  50.             if(i >= 10000)
  51.             {
  52.                 seperate(i, num);
  53.                 if(num[1]==1 && num[5]==2)
  54.                 {
  55.                     printf("%d/n", i);
  56.                     for(j = 1; j <= n; ++j) printf("%d ", num[j]);
  57.                     exit(0);
  58.                 }
  59.                 int t=0;
  60.                 bool zero=false;
  61.                 for(j = 1; j <= n; ++j)
  62.                 {
  63.                     t += num[j];
  64.                     if(num[j]==0) zero=1;
  65.                 }
  66.                 if(t == sum)
  67.                 {
  68.                     p1[num[1]][ ++p1[num[1]][0] ] = i;
  69.                     p3[num[3]][ ++p3[num[3]][0] ] = i;
  70.                     if(!zero) p15[num[1]][num[5]][ ++p15[num[1]][num[5]][0] ] = i;
  71.                     // zero!!
  72.                     p124[num[1]][num[2]][num[4]][ ++p124[num[1]][num[2]][num[4]][0] ] = i;
  73.                     p234[num[2]][num[3]][num[4]][ ++p234[num[2]][num[3]][num[4]][0] ] = i;
  74.                     p135[num[1]][num[3]][num[5]][ ++p135[num[1]][num[3]][num[5]][0] ] = i;
  75.                 }
  76.             }
  77.         }
  78.         for(j = 1; j <= p[0] && p[j]*i < N; ++j)
  79.         {
  80.             del[p[j]*i] = true;
  81.             if(i%p[j]==0) break;
  82.         }
  83.     }
  84. }
  85. void update()
  86. {
  87.     memcpy(ans[++ans_num].a, a, sizeof(a));
  88. }
  89. bool fail_row(int row)
  90. {
  91.     int i, x=0, t=0;
  92.     for(i = 1; i <= n; ++i)
  93.     {
  94.         x *= 10;
  95.         x += a[row][i];
  96.         t += a[row][i];
  97.     }
  98.     return t!=sum || del[x];
  99. }
  100. bool fail_col(int col)
  101. {
  102.     int i, x=0, t=0;
  103.     for(i = 1; i <= n; ++i)
  104.     {
  105.         x *= 10;
  106.         x += a[i][col];
  107.         t += a[i][col];
  108.     }
  109.     return t!=sum || del[x];
  110. }
  111. /*
  112. process order
  113. 03332
  114. 71?28
  115. 64156
  116. 72?18
  117. 24?51
  118. the set of prime
  119. p1
  120. p3
  121. p15
  122. p124
  123. p234
  124. p135
  125. */
  126. int main()
  127. {
  128.     int i, j, k, d1, d2, r1, c2, c4, r3, c1, c5;
  129.     int s[3];
  130.     char num[n+1];
  131.     freopen("prime3.in","r",stdin);
  132.     freopen("prime3.out","w",stdout);
  133.     scanf("%d%d", &sum, &a[1][1]);
  134.     get_prime();
  135.     for(d1 = 1; d1 <= p1[a[1][1]][0]; ++d1)
  136.     {
  137.         seperate(p1[a[1][1]][d1], num);
  138.         for(i = 2; i <= n; ++i)
  139.         {
  140.             a[i][i] = num[i];
  141.         }
  142.         for(d2 = 1; d2 <= p3[a[3][3]][0]; ++d2)
  143.         {
  144.             seperate(p3[a[3][3]][d2], num);
  145.             for(i = 1; i <= n; ++i)
  146.             {
  147.                 a[n-i+1][i] = num[i];
  148.             }
  149.             for(r1 = 1; r1 <= p15[a[1][1]][a[1][n]][0]; ++r1)
  150.             {
  151.                 seperate(p15[a[1][1]][a[1][n]][r1], num);
  152.                 for(i = 2; i < n; ++i)
  153.                 {
  154.                     a[1][i] = num[i];
  155.                 }
  156.                 for(c2 = 1; c2 <= p124[a[1][2]][a[2][2]][a[4][2]][0]; ++c2)
  157.                 {
  158.                     seperate(p124[a[1][2]][a[2][2]][a[4][2]][c2], num);
  159.                     a[3][2] = num[3], a[5][2] = num[5];
  160.                     for(c4 = 1; c4 <= p124[a[1][4]][a[2][4]][a[4][4]][0]; ++c4)
  161.                     {
  162.                         seperate( p124[a[1][4]][a[2][4]][a[4][4]][c4], num);
  163.                         a[3][4] = num[3], a[5][4] = num[5];
  164.                         for(r3 = 1; r3 <= p234[a[3][2]][a[3][3]][a[3][4]][0]; ++r3)
  165.                         {
  166.                             seperate(p234[a[3][2]][a[3][3]][a[3][4]][r3], num);
  167.                             a[3][1] = num[1], a[3][5] = num[5];
  168.                             for(c1 = 1; c1 <= p135[a[1][1]][a[3][1]][a[5][1]][0]; ++c1)
  169.                             {
  170.                                 seperate(p135[a[1][1]][a[3][1]][a[5][1]][c1], num);
  171.                                 if(num[2]==0 || num[4]==0) continue;
  172.                                 a[2][1] = num[2], a[4][1] = num[4];
  173.                                 for(c5 = 1; c5 <= p135[a[1][5]][a[3][5]][a[5][5]][0]; ++c5)
  174.                                 {
  175.                                     seperate( p135[a[1][5]][a[3][5]][a[5][5]][c5], num);
  176.                                     a[2][5] = num[2], a[4][5] = num[4];
  177.                                     a[2][3] = sum - (a[2][1]+a[2][2]+a[2][4]+a[2][5]);
  178.                                     if(a[2][3]<0 || a[2][3]>9 || fail_row(2)) continue;
  179.                                     // 0<=a[2][i]<=9 && sum(a[2])==sum && prime(a[2])
  180.                                     a[4][3] = sum - (a[4][1]+a[4][2]+a[4][4]+a[4][5]);
  181.                                     if(a[4][3]<0 || a[4][3]>9 || fail_row(4)) continue;
  182.                                     a[5][3] = sum - (a[1][3]+a[2][3]+a[3][3]+a[4][3]);
  183.                                     if(a[5][3]<0 || a[5][3]>9 || fail_col(3) || fail_row(5)) continue;
  184.                                     update();
  185.                                 }
  186.                             }
  187.                         }
  188.                     }
  189.                 }
  190.             }
  191.         }
  192.     }
  193.     for(i = 1; i <= ans_num; ++i)
  194.     {
  195.         out[i] = ans+i;
  196.     }
  197.     sort(out+1, out+ans_num+1, cmp);
  198.     for(i = 1; i <= ans_num; ++i)
  199.     {
  200.         for(j = 1; j <= n; ++j)
  201.         {
  202.             for(k = 1; k <= n; ++k)
  203.             {
  204.                 printf("%d", out[i]->a[j][k]);
  205.             }
  206.             putchar('/n');
  207.         }
  208.         if(i!=ans_num) putchar('/n');
  209.     }
  210.     return 0;
  211. }


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值