BZOJ 3990 [SDOI2015]排序

 题解:

 首先很容易看出各个操作是互不影响的,即对于一个合法的操作序列,我们可以任意交换两个操作的位置而不影响合法性.

 因此我们可以忽略操作先后的影响,只考虑这个操作是否会出现在操作序列中.

 如果用2n枚举操作集S再验证,很难有思路.

 不如固定操作依次为1-n,然后进行暴搜.

 由于这题特殊的性质,暴搜的状态实际并不多.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<iomanip>
using namespace std;
#define ll long long
#define db double 
#define up(i,j,n) for(int i=j;i<n;i++)
#define pii pair<int,int>
#define uint unsigned int
#define FILE "dealing"
int read(){
	int x=0,f=1,ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return x*f;
}
template<class T> bool cmax(T& a,T b){return a<b?a=b,true:false;}
template<class T> bool cmin(T& a,T b){return a>b?a=b,true:false;}
const int maxn=4100,limit=128,inf=1000000000;
int a[maxn],n;
int fac[15];
int ans;
void Swap(int a[],int b[],int len){
	up(i,0,len)swap(a[i],b[i]);
}
void dfs(int pos,int cnt){
	if(pos==n){
		ans+=fac[cnt];
		return;
	}
	int top=0,q[3]={0,0,0};int len=1<<pos+1;
	for(int i=0;i<1<<n;i+=len){
		if(a[i+(len>>1)-1]+1!=a[i+(len>>1)]){
			if(top==2)return;
			q[++top]=i;
		}
	}
	if(top==0){
		dfs(pos+1,cnt);
		return;
	}
	if(top==1){
		int i=q[1];
		if(a[i+len-1]+1==a[i]){
			Swap(a+i,a+i+(len>>1),len>>1);
			dfs(pos+1,cnt+1);
			Swap(a+i,a+i+(len>>1),len>>1);
		}
		return;
	}
	if(top==2){
		int i=q[1],j=q[2];
		if(a[i+(len>>1)]==a[j+(len>>1)-1]+1&&a[j+(len>>1)]==a[i+(len>>1)-1]+1){
			Swap(a+i,a+j,len>>1);
			dfs(pos+1,cnt+1);
			Swap(a+i,a+j,len>>1);
			Swap(a+i+(len>>1),a+j+(len>>1),len>>1);
			dfs(pos+1,cnt+1);
			Swap(a+i+(len>>1),a+j+(len>>1),len>>1);
		}
		if(a[i]==a[j+(len>>1)-1]+1&&a[j+(len)-1]+1==a[i+(len>>1)]){
			Swap(a+i,a+j+(len>>1),len>>1);
			dfs(pos+1,cnt+1);
			Swap(a+i,a+j+(len>>1),len>>1);
		}
		if(a[j]==a[i+(len>>1)-1]+1&&a[i+(len)-1]+1==a[j+(len>>1)]){
			Swap(a+j,a+i+(len>>1),len>>1);
			dfs(pos+1,cnt+1);
			Swap(a+j,a+i+(len>>1),len>>1);
		}
		return;
	}
}
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	n=read();
	fac[0]=1;
	up(i,1,n+1)fac[i]=fac[i-1]*i;
	up(i,0,1<<n)a[i]=read();
	dfs(0,0);
	printf("%d\n",ans);
	return 0;
}

  

posted @ 2017-03-15 14:23  CHADLZX  阅读(113)  评论(0编辑  收藏  举报