搜索-洛谷P3322 [SDOI2015]排序

https://daniu.luogu.org/problem/show?pid=3322
假设分块的长度是2^i
那我们把i从1到n枚举;
枚举到i时,会分成(2^n)/(2^i)块;
我们就让这几个块内的指递增,且每个相邻的数相差1;
如果我们不能维护成功,那么return;
怎么维护呢;
如果有n个块时不递增的;
那么n>2显然就无法维护了;
n=1我们可以试试把这个块分成两半,然后交换两半,看看可不可以;
n=2那我们把两个大块分成4个小块,两两组合,组合时要保证只能交换块一次;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define Ll long long
using namespace std;
int a[4100];
Ll ans,f[15];
int n;
void swa(int x,int y,int z){
    for(int i=0;i<z;i++)
        swap(a[x+i],a[y+i]);
}
void dfs(int m,int sum){
    if(m>n){ans+=f[sum];return;}
    int l=1<<m;
    int q[5]{0},top=0;
    for(int i=1;i<=(1<<n);i+=l){
        int x=(i+i+l-1)/2;
        if(a[x]+1!=a[x+1])q[++top]=i;
        if(top==3)return;
    }
    if(top==0){
        dfs(m+1,sum);
    }else
    if(top==1){
        int i=q[1];
        int x=i+l-1;
        if(a[i]==a[x]+1){
            x=(i+i+l-1)/2;                               
            swa(i,x+1,l/2);
            dfs(m+1,sum+1);
            swa(i,x+1,l/2);
        }   
    }else
    if(top==2){
        int x1=q[1],x2=x1+l/2,x3=q[2],x4=x3+l/2;
        int y1=x1+l/2-1,y2=x2+l/2-1,y3=x3+l/2-1,y4=x4+l/2-1;
        if(a[y3]+1==a[x2]&&a[y1]+1==a[x4]){
            swa(x1,x3,l/2);
            dfs(m+1,sum+1);
            swa(x1,x3,l/2);
            swa(x2,x4,l/2);
            dfs(m+1,sum+1);
            swa(x2,x4,l/2);
        }
        if(a[y3]+1==a[x1]&&a[y4]+1==a[x2]){
            swa(x1,x4,l/2);
            dfs(m+1,sum+1);
            swa(x1,x4,l/2);
        }
        if(a[y1]+1==a[x3]&&a[y2]+1==a[x4]){
            swa(x2,x3,l/2);
            dfs(m+1,sum+1);
            swa(x2,x3,l/2);
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=(1<<n);i++)scanf("%d",&a[i]);                                              
    f[1]=1;
    for(int i=2;i<=n;i++)f[i]=f[i-1]*i;
    dfs(1,0);
    printf("%lld",ans);
}
posted @ 2017-03-28 10:58  largecube233  阅读(525)  评论(0编辑  收藏  举报