【bzoj3990】 SDOI2015排序 dfs搜索+剪枝
2015-07-27 16:37
399 查看
航爷出的题果然太耗脑子了,看完gty大哥的题解才会做。首先有一个结论,操作序列的顺序不影响最终结果,所以我们搜出一种合法的操作组合之后乘以步骤数的阶乘就可以了。然后我们发现,从小到大搜索,当第i次操作完成后,每一个2^i的段必须变成有序的,而且每次操作只允许有4个顺序不同的,这样一交换才可能变成有序。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #define maxn 10010 using namespace std; int n; int a[maxn]; long long c[13]; long long ans; void swap(int i,int j,int len) { for (int k=1;k<=len;k++) swap(a[i+k-1],a[j+k-1]); } bool check(int k) { for (int i=1;i<=(1<<(n-k));i++) if (a[(i-1)*(1<<k)+1]+(1<<(k-1))!=a[(i-1)*(1<<k)+1+(1<<(k-1))]) return 0; return 1; } void dfs(int now,int num) { if (now && !check(now)) return; if (now==n) {ans+=c[num];return;} dfs(now+1,num); int tmp[5],tot=0; for (int i=1;i<=(1<<(n-(now+1)+1));i+=2) if (a[i*(1<<now)+1]!=a[(i-1)*(1<<now)+1]+(1<<now)) { if (tot==4) return; else tmp[++tot]=i,tmp[++tot]=i+1; } if (!tot) return; for (int i=1;i<tot;i++) for (int j=i+1;j<=tot;j++) { swap((1<<now)*(tmp[i]-1)+1,(1<<now)*(tmp[j]-1)+1,(1<<now)); dfs(now+1,num+1); swap((1<<now)*(tmp[i]-1)+1,(1<<now)*(tmp[j]-1)+1,(1<<now)); } } int main() { c[0]=1; for (int i=1;i<=12;i++) c[i]=c[i-1]*i; scanf("%d",&n); for (int i=1;i<=(1<<n);i++) scanf("%d",&a[i]); dfs(0,0); printf("%lld\n",ans); return 0; }
相关文章推荐
- idea 14 Error: Failed to create a child event loop
- HDUOJ 18岁生日 题目1201
- POJ 1007 DNA Sorting (归并排序)
- linux操作链路层的数据
- hdu 1203 I NEED A OFFER! dp
- GDB调试(一)
- hdu4770Lights Against Dudely 暴力搜索
- [MFC]MFC输出到EXCEL表格并画图表
- Java中Class类详解、用法及泛化
- 计算机网络基础
- lufylegend库 LButton
- CentOS使用指南一(网络配置)
- openGL多边形内填充
- NYOJ 58
- 网站CSS写在html里面的好处
- Codeforces Round #313 (Div. 2)
- Nginx/LVS/HAProxy负载均衡软件的优缺点详解
- objective-C中category与extension的探究——关于extension(类扩展)的实验和总结
- Oracle 经典练习语句
- lufylegend库 鼠标事件 循环事件 键盘事件