好了做了SDOI day1的3道题,来讲下做法及感想吧
T1:排序(暴力,搜索)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3990
我们可以很轻易的发现,对于一个操作方案,交换两个操作顺序不会影响答案,因此我们可以从小到大枚举答案,可以发现,对于第i种操作过后,每个2^i的块必须是连续的
那么在第i种操作之前,最多只能有2个块不连续,那么如果没有块不连续,不用执行该种操作;只有一个块不连续,交换这个块的两小块;两个块分4种情况讨论,用dfs暴力搜索即可
时间复杂度看上去是O(4^N),但好像可以证出复杂度其实是O(2^NlogN)N=20都能跑过
CODE:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define maxn 5000 7 int a[maxn],n,f[15]; 8 long long ans=0; 9 inline void _swap(int *a,int *b,int step) { 10 for (int i=1;i<=step;i++) swap(a[i],b[i]); 11 } 12 inline bool check(int x,int y) {return a[x+y]+1==a[x+y+1];} 13 int dfs(int x,int y) { 14 if (x==n+1) return ans+=f[y]; 15 int w[5],cnt=0; 16 int step=1<<(x-1); 17 for (int i=0;i<1<<n;i+=1<<x) { 18 if (!check(i,step)) w[++cnt]=i; 19 if (cnt>2) return 0; 20 } 21 if (cnt==0) dfs(x+1,y); 22 if (cnt==1) { 23 _swap(a+w[1],a+w[1]+step,step); 24 if (check(w[1],step)) dfs(x+1,y+1); 25 _swap(a+w[1],a+w[1]+step,step); 26 } 27 if (cnt==2) { 28 int *l1=a+w[1],*l2=a+w[2],*r1=a+w[1]+step,*r2=a+w[2]+step; 29 _swap(l1,l2,step); 30 if (check(w[1],step)&&check(w[2],step)) dfs(x+1,y+1); 31 _swap(l1,l2,step); 32 _swap(l1,r2,step); 33 if (check(w[1],step)&&check(w[2],step)) dfs(x+1,y+1); 34 _swap(l1,r2,step); 35 _swap(r1,l2,step); 36 if (check(w[1],step)&&check(w[2],step)) dfs(x+1,y+1); 37 _swap(r1,l2,step); 38 _swap(r1,r2,step); 39 if (check(w[1],step)&&check(w[2],step)) dfs(x+1,y+1); 40 _swap(r1,r2,step); 41 } 42 } 43 44 int main(){ 45 scanf("%d",&n); 46 f[0]=1; 47 for (int i=1;i<=n;i++) f[i]=f[i-1]*i; 48 for (int i=1;i<=(1<<n);i++) { 49 scanf("%d",a+i); 50 a[i]--; 51 } 52 dfs(1,0); 53 printf("%lld\n",ans); 54 return 0; 55 }