BZOJ 3990 排序 发表于 2017-01-15 | 更新于 2018-06-18 Link唉,还是too young。 Solution操作序列的顺序不影响最终的结果。 于是就枚举操作序列,最终乘上步数的阶乘。 及时排除掉不可能排好的情况。 从小到大DFS,有点归并的感觉。 Code123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869//Code by Lucida#include<bits/stdc++.h>#define get(x) scanf("%d",&x)//#define debug(x) std::cout<<#x<<'='<<x<<std::endltemplate <class T> inline bool chkmx(T &a,const T &b){return a<b?a=b,1:0;}template <class T> inline bool chkmn(T &a,const T &b){return a>b?a=b,1:0;}typedef long long LL;using std::swap;const int N=12,MAXN=20,MAXL=1<<13;LL fac[MAXN];int a[MAXL],n;void swap_n(int *x,int n,int *y){ for(int i=1;i<=n;i++) swap(*x++,*y++);}bool check(int d){ for(int i=1;i+d<=(1<<n);i+=d*2) if(a[i]+d!=a[i+d]) return 0; return 1;}LL DFS(int cur,int cnt)//进行完cnt,要进行cur{ if(cur==n) return fac[cnt]; int stack[5],top=0; int d=(1<<cur); for(int i=1;i+d<=(1<<n);i+=d*2) { if(a[i]+d!=a[i+d]) { if(top==4) return 0; stack[++top]=i; stack[++top]=i+d; } } if(top==0) return DFS(cur+1,cnt); LL res=0; if(top==2) { swap_n(a+stack[1],d,a+stack[2]); res=DFS(cur+1,cnt+1); swap_n(a+stack[1],d,a+stack[2]); } else { for(int i=1;i<=top-1;i++) for(int j=i+1;j<=top;j++) { swap_n(a+stack[i],d,a+stack[j]); if(check(d)) res+=DFS(cur+1,cnt+1); swap_n(a+stack[i],d,a+stack[j]); } } return res;}int main(){ fac[0]=1;for(int i=1;i<=N;i++) fac[i]=fac[i-1]*i;// freopen("input","r",stdin); get(n); for(int i=1;i<=(1<<n);i++) get(a[i]); printf("%lld\n",DFS(0,0)); return 0;}/* AC Record(Bugs) * WA * 看题解没研究清楚 实现不同 */