loli的搜索测试-我真不知道是第多少次了

  搜索测试

  又到了....并不激动人心的搜索测试时间。

  今天和以前还是有一点不一样的,新高二的学长们也参加了(也就是说我们又要被吊打了)

  话不多说,看题:

  fz:填一个5*5的质数方阵,要求每行,每列,两个对角线上的数从左往右连起来都是质数,且每个质数都没有前导零,且每个质数的每位相加之和是一个给定的数,且左上角的数字给定,输出左右方案,没有就输出NONE。

  是一个看起来非常可做,实际上非常不可做的题目,我写了1.5h之后样例竟然还要跑15s,是的你没有看错,就是十五秒,于是我弃疗了。我的思路是,首先制作一个合法的质数表,搜出第一行,再根据第一行(也就是每一列已经有了第一个数)来搜出五个竖列,第一行和第一列的数字都不能带0,之后每搜一个就判一判合法性。听起来已经挺优化的了,然而光荣爆零。最高分也只有40分,还是一个高二的学长写的。std是一个5kb的pascal文件,完全没有去读他的欲望,于是这个题就先咕咕咕了,贴一份我的0分代码吧。 

  
  1 # include <cstdio>
  2 # include <iostream>
  3 # define R register int
  4 
  5 using namespace std;
  6 
  7 const int maxn=99999;
  8 bool pri[100005];
  9 int ans=0,cnt,s,beg,firs,t[6],P[maxn];
 10 
 11 int div (int x)
 12 {
 13     int S=0;
 14     while (x)
 15     {
 16         S+=x%10;
 17         x/=10;
 18     }
 19     return S;
 20 }
 21 
 22 int sw (int x,int i)
 23 {
 24     if(i==1) return x/10000;
 25     if(i==2) return x/1000%10;
 26     if(i==3) return x/100%10;
 27     if(i==4) return x/10%10;
 28     return x%10;
 29 }
 30 
 31 void print()
 32 {
 33     for (R i=1;i<=5;++i)
 34     {
 35         for (R j=1;j<=5;++j)
 36             printf("%d",sw(t[j],i));
 37         printf("\n");
 38     }
 39     printf("\n");
 40 }
 41 
 42 bool check()
 43 {
 44     int a=0;
 45     for (R i=1;i<=5;++i)
 46     {
 47         a=0;
 48         for (R j=1;j<=5;++j)
 49             a=a*10+sw(t[j],i);
 50         if(pri[a]==false) return false;
 51     }
 52     a=0;
 53     for (R i=1;i<=5;++i)
 54         a=a*10+sw(t[i],i);
 55     if(pri[a]==false) return false;
 56     a=0;
 57     for (R i=1;i<=5;++i)
 58         a=a*10+sw(t[i],5-i+1);
 59     if(pri[a]==false) return false;
 60     return true;
 61 }
 62 
 63 void dfs (int x)
 64 {
 65     int a,f;
 66     if(x==6)
 67     {
 68         if(check()) ans++,print();
 69         return ;
 70     }
 71     if(x==1)
 72     {
 73         for (R i=1;i<=cnt;++i)
 74         {
 75             if(P[i]/10000!=sw(P[i],x)) continue;
 76             if(sw(P[i],1)==0||sw(P[i],2)==0||sw(P[i],3)==0||sw(P[i],4)==0||sw(P[i],5)==0) continue;
 77             t[1]=P[i];
 78             dfs(2);
 79         }
 80     }
 81     else
 82     {
 83         for (R i=1;i<=cnt;++i)
 84         {
 85             if(P[i]/10000!=sw(firs,x)) continue;
 86             t[x]=P[i];
 87             f=0;
 88             for (R j=1;j<=5;++j)
 89             {
 90                 a=0;
 91                 for (R k=1;k<=x;++k)
 92                     a+=sw(t[k],j);
 93                 if(a>s) f=1;
 94             }
 95             if(f) continue;
 96             dfs(x+1);
 97         }
 98     }
 99 }
100 
101 int main()
102 {
103     freopen("fz.in","r",stdin);
104     freopen("fz.out","w",stdout);
105     
106     scanf("%d%d",&s,&beg);
107     for (R i=2;i<=maxn;++i)
108     {
109         if(pri[i]) continue;
110         for (R j=2;j*i<=maxn;++j)    
111         pri[i*j]=true;
112     }
113     for (R i=1;i<=9999;++i)
114         pri[i]=false;
115     for (R i=10000;i<=99999;++i)
116     {
117         pri[i]^=1;
118         if(pri[i]&&div(i)!=s) pri[i]=false;
119     }
120     for (R i=10000;i<=99999;++i)
121         if(pri[i]) P[++cnt]=i;
122     for (R i=1;i<=cnt;++i)
123     {
124         if(P[i]/10000!=beg) continue;
125         if(sw(P[i],1)==0||sw(P[i],2)==0||sw(P[i],3)==0||sw(P[i],4)==0||sw(P[i],5)==0) continue;
126         firs=P[i];
127         dfs(1);
128     }
129     if(ans==0) printf("NONE");
130     fclose(stdin);
131     fclose(stdout);    
132     return 0;
133 }
fz

  

  gift:很像背包,但是数据范围极大只能搜索的背包题,似乎要用$meet$ $in$ $the$ $middle$来做,但是爆搜可以得到$70$.

  square:poj上一个挺经典的题目,就是问一些火柴棍删掉多少条才能破坏所有的正方形。不知道为什么大家都没有写这个题,咕咕咕?

  

posted @ 2018-08-30 16:33  shzr  阅读(213)  评论(0编辑  收藏  举报