好了做了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 }
View Code

相关文章: