考试时没想出正解,最后打了个暴力骗分,暴力还好.....就是搜索每个状态,然后暴力枚举,以后如果有时间还是要打
正解的,但我太蒟蒻了,打不出来......
然后就是正解也是搜索
首先明白一条性质
不管是怎样的操作,只要每种操作都确定下,不管怎样改变次序,都不会改变结果。
(关于证明,可以自己把每个位置想象成一个块,每次移动块也随之移动,不管次序结果相同。)
然后此题可以分为四个情况
设搜索中的区间长度为2^k,so当前要将2^(k-1)的区间都搞成递增的;
当此时不符合递增条件的有一个2^k区间,就将它内部互换
当两个时,就需要分四种情况交叉呼唤(这时最好不要用数组存储要操作的块数,因为搜完后会回溯)
当无时直接搜索下一个
当太多时return反正也改不完。
代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 #include<vector> 7 #include<string> 8 #define MAXN 21000 9 #define pt printf("--------- "); 10 using namespace std; 11 int tot; 12 bool bian[MAXN]; 13 int base[MAXN];int n; 14 int a[MAXN]; 15 int jie[MAXN]; 16 void qian(int k,int x,int y)//2^k长的段 第x段 第y段 17 { 18 int star=(x-1)*base[k]+1; 19 int la=x*base[k]; 20 for(int i=star;i<=la;++i) 21 { 22 swap(a[i],a[i+(y-x)*base[k]]); 23 } 24 } 25 int sum; 26 vector<int>wr;vector<int>ci; 27 int work(int kx,int xx,int yy,int cc1,int cc2) 28 { 29 qian(kx-1,xx,yy); 30 int star_1=(cc1-1)*base[kx]+base[kx-1]; 31 int star_2=(cc2-1)*base[kx]+base[kx-1]; 32 //printf("2————搜索 a[%d]=%d a[%d]=%d wr0%d wr1=%d %d ",star_1,a[star_1],star_2,a[star_2],xx,yy,kx+1); 33 if(a[star_1]+1!=a[star_1+1]||a[star_2]+1!=a[star_2+1]) 34 { 35 qian(kx-1,xx,yy); 36 return 0; 37 } 38 return 1; 39 } 40 void DFS(int kx,int cnt)//搜索长度为2^k区间 然后用了cnt个操作 41 { 42 if(kx>n) 43 { 44 for(int i=1;i<=base[n];++i) 45 {if(a[i-1]+1!=a[i]) return ;} 46 sum+=jie[cnt]; 47 // printf("sum=%d cnt=%d ",sum,cnt); 48 return ; 49 } 50 // printf("kx=%d cnt=%d ",kx,cnt); 51 int duan=base[n-kx]; 52 wr.clear();ci.clear(); 53 for(int k=1;k<=duan;++k) 54 { 55 int star=(k-1)*base[kx]+base[kx-1];// ([][*]|[*][]) 56 if(a[star]+1!=a[star+1]) 57 { 58 // printf("第%d段 a[%d]=%d a[%d]=%d duan=%d %d ",k,star,a[star],star+1,a[star+1],k*2-1,k*2); 59 wr.push_back(k*2-1); 60 wr.push_back(k*2); 61 ci.push_back(k); 62 } 63 } 64 if(wr.size()>4) 65 { 66 return ; 67 } 68 if(wr.size()==2) 69 { 70 qian(kx-1,wr[0],wr[1]); 71 int star=(ci[0]-1)*base[kx]+base[kx-1]; 72 if(a[star]+1!=a[star+1]) 73 { 74 qian(kx-1,wr[0],wr[1]); 75 return ; 76 } 77 else 78 { 79 int xx=wr[0],yy=wr[1]; 80 // printf("1————搜索 a[%d]=%d a[%d]=%d wr0%d wr1=%d %d ",star,a[star],star+1,a[star+1],wr[0],wr[1],kx+1); 81 DFS(kx+1,cnt+1); 82 qian(kx-1,xx,yy); 83 } 84 } 85 if(wr.size()==4) 86 { 87 int xx1=wr[0],xx2=wr[1],yy1=wr[2],yy2=wr[3]; 88 int cc1=ci[0];int cc2=ci[1]; 89 if(work(kx,xx1,yy1,cc1,cc2)==1) 90 { 91 DFS(kx+1,cnt+1); 92 qian(kx-1,xx1,yy1); 93 // printf("2----%d %d ",xx1,yy1); 94 } 95 if(work(kx,xx1,yy2,cc1,cc2)==1) 96 { 97 DFS(kx+1,cnt+1); 98 qian(kx-1,xx1,yy2); 99 // printf("2----%d %d ",xx1,yy2); 100 } 101 if(work(kx,xx2,yy1,cc1,cc2)==1) 102 { 103 DFS(kx+1,cnt+1); 104 qian(kx-1,xx2,yy1); 105 // printf("2----%d %d ",xx2,yy1); 106 } 107 if(work(kx,xx2,yy2,cc1,cc2)==1) 108 { 109 DFS(kx+1,cnt+1); 110 qian(kx-1,xx2,yy2); 111 // printf("2----%d %d ",xx2,yy2); 112 } 113 } 114 if(wr.size()==0) 115 { 116 DFS(kx+1,cnt); 117 } 118 return ; 119 } 120 int main() 121 { 122 scanf("%d",&n); 123 base[0]=1;jie[0]=1; 124 for(int i=1;i<=n;++i) 125 { 126 base[i]=base[i-1]*2;jie[i]=jie[i-1]*i; 127 } 128 for(int i=1;i<=base[n];++i) 129 { 130 scanf("%d",&a[i]); 131 } 132 DFS(1,0); 133 printf("%d ",sum); 134 }