搜索测试
又到了....并不激动人心的搜索测试时间。
今天和以前还是有一点不一样的,新高二的学长们也参加了(也就是说我们又要被吊打了)
话不多说,看题:
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(" "); 38 } 39 printf(" "); 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 }
gift:很像背包,但是数据范围极大只能搜索的背包题,似乎要用$meet$ $in$ $the$ $middle$来做,但是爆搜可以得到$70$.
square:poj上一个挺经典的题目,就是问一些火柴棍删掉多少条才能破坏所有的正方形。不知道为什么大家都没有写这个题,咕咕咕?