http://172.20.6.3/Problem_Show.asp?id=1385
刚开始想的时候一直以为同一排不同的拉灯顺序对结果是有影响的,手推了好多遍才发现拉灯结果只和拉的灯有关,这也要打表,可以说非常智障了。
如果从上向下寻找拉的灯,那么每一排全暗主要相关的是下一排(通过下一排补齐)和初始状态,而每一排的初始状态是和其本身和上一排有关的,那么只要找出第一排所有的拉灯方案(2^5种)然后对这几种方案模拟一遍找能全亮且步数最小的方案。
锻炼搜索能力的好题
注意小于6步…交的时候没看见,日常眼瞎1/1。
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int maxn=(1<<5)+10; 9 int a[6]={}; 10 char ch[10]={}; 11 int f[maxn]={};//第一行操作数量 12 int f1[maxn]={};//第一行操作对第二行的影响 13 int nn[maxn]={};//第一行操作后得到的数 14 //以上三个通过dfs计算 15 int aa[maxn]={};//下一行来填满这一行对下一行的影响 16 int bb[maxn]={};//对下下一行的影响 17 int z[maxn]={};//操作数量 18 //以上三个预处理 19 int ma=maxn-11; 20 void dfs1(int k,int num,int d,int z){ 21 if(k>=5){ 22 f[z]=d;f1[z]=z;nn[z]=num; 23 return; 24 } 25 int w=1<<k,w1; 26 if(k>=1)w1=(7<<(k-1))&ma; 27 else w1=7/2; 28 dfs1(k+1,num,d,z); 29 dfs1(k+1,num^w1,d+1,z^w); 30 } 31 int main(){ 32 //freopen("wtf.in","r",stdin); 33 //freopen("wtf.out","w",stdout); 34 int T;scanf("%d",&T); 35 for(int i=0;i<=ma;i++){ 36 int k=4; 37 for(int j=1;j<=5;j++){ 38 int w=1<<k,w1; 39 if(k>=1)w1=(7<<(k-1))&ma; 40 else w1=7/2; 41 if((i&w)==0) aa[i]=aa[i]^w1,z[i]++; 42 k--; 43 } 44 bb[i]=(~i)&ma; 45 } 46 while(T-->0){ 47 memset(a,0,sizeof(a)); 48 for(int i=1;i<=5;i++){ 49 scanf("%s",&ch); 50 for(int j=1;j<=5;j++){ 51 a[i]*=2; 52 a[i]+=ch[j-1]-‘0‘; 53 } 54 }memset(f,63,sizeof(f)); 55 int da=f[1]; 56 dfs1(0,a[1],0,0); 57 int ans=da; 58 for(int i=0;i<=ma;i++){ 59 int nex1=aa[nn[i]],nex2=bb[nn[i]],bu=f[i]+z[nn[i]],num=f1[i],zz; 60 for(int j=2;j<=5;j++){ 61 num=num^a[j]^nex1;//初始状态 62 nex1=aa[num];//填满需要几步 63 if(j==5&&num==ma)ans=min(ans,bu); 64 bu+=z[num]; 65 zz=nex2;nex2=bb[num];num=zz;//填满这一行对下下一行的影响 66 } 67 } 68 if(ans>6)printf("%d\n",-1); 69 else printf("%d\n",ans); 70 } 71 return 0; 72 }
时间: 2024-10-29 19:07:58