[sdoi2015]排序(搜索+剪枝优化)
Description
小A有一个1-2^N的排列A[1..2^N],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1<=i<=N),第i中操作为将序列从左到右划分为2^{N-i+1}段,每段恰好包括2^{i-1}个数,然后整体交换其中两段.小A想知道可以将数组A从小到大排序的不同的操作序列有多少个,小A认为两个操作序列不同,当且仅当操作个数不同,或者至少一个操作不同(种类不同或者操作位置不同).
Input
第一行,一个整数N
Output
一个整数表示答案
Sample Input
7 8 5 6 1 2 4 3
Sample Output
HINT
100%的数据, 1<=N<=12.
题解:
......搜索送命题
对于菜得不能再菜的垃圾博主,搜索真是这世界上最难的算法(dalao勿喷)。
考试时看到这题,觉得是道数学题或者是一道数据结构加数学题,结果看题解发现是一道搜索。
不会写搜索的垃圾博主当场吓尿。
但考试时输出阶乘qj测试点得了15pts,运气不错
咳咳...言归正传
其实首先要想到一个性质就是对于一个操作序列的顺序是不影响他的合法性的,也就是说每次多加一种操作对答案的贡献是阶乘的这也就是我没爆零的原因。
那么我们就只需要确定每个操作是不是要选就可以了。
我们从小到大dfs,dfs(now,x)表示选了now种方法,现在判断第x种方法。
显然递归入口dfs(0,1)。
然后我们考虑怎样剪枝。
实际上交换的过程就是把不合法的子序列进行交换得到合法的子序列。
然后我们就可以每次扫一遍,找出对于每次操作x,不合法的序列个数及不合法序列的开始位置以便交换。
如果有两个以上不合法的子序列那就完戏了,直接return。
如果没有不合法的子序列,那么就不需要进行这种操作,直接搜下一层。
如果有一个这种子序列,那么交换他的前一半和后一半,再判断是否合法,再进行搜索。
如果有两个这种子序列,那么判断四种情况,在进行搜索。
很多神犇只说四种情况,并没有说明白是哪四种情况,坑害了我这种懵逼的蒟蒻
其实也很好想就是判断前一段的前一段和后一段的前一段交换,前一段的后一段和后一段的前一段,前一段的前一段和后一段的后一段,前一段的后一段和后一段的前一段。
就似这四种情况辣。
另外还有要注意的是就是在写交换和判断两个过程时一定要处理好循环的边界问题,博主就因为这个被卡了好长时间。
(附上本人丑陋的代码)、
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<queue> 6 #include<vector> 7 #include<algorithm> 8 using namespace std; 9 int fac[15],power[15];int n;int num; 10 int a[1<<12|5]; 11 int res=0; 12 int qpower(int a,int b){ 13 int ans=1; 14 while(b){ 15 if(b&1) ans=ans*a; 16 b>>=1; 17 a=a*a; 18 } 19 return ans; 20 } 21 int check(int x,int k){ 22 for(int i=1;i<power[k];i++){//不要右边界 23 if(a[x+i]!=a[x+i-1]+1){ 24 return 1; 25 } 26 } 27 return 0; 28 } 29 void swap(int x,int y,int k){ 30 for(int i=0;i<power[k];i++){//左右边界都不要 31 int t; 32 t=a[x+i]; 33 a[x+i]=a[y+i]; 34 a[y+i]=t; 35 } 36 } 37 void dfs(int now,int x){ 38 //cout<<x<<" "<<now<<endl; 39 if(x==n+1){ 40 res+=fac[now]; 41 return ; 42 } 43 int pos1=0;int pos2=0;int cnt=0; 44 for(int i=1;i<=num;i+=power[x]){ 45 if(check(i,x)){ 46 cnt++; 47 if(cnt>=3) break; 48 if(!pos2){ 49 if(!pos1){ 50 pos1=i; 51 } 52 else pos2=i; 53 } 54 } 55 } 56 //cout<<cnt<<" "<<pos1<<" "<<pos2<<endl; 57 if(cnt>2) return ; 58 if(cnt==0){ 59 dfs(now,x+1); 60 } 61 if(cnt==1){ 62 swap(pos1,pos1+power[x-1],x-1); 63 dfs(now+1,x+1); 64 swap(pos1,pos1+power[x-1],x-1); 65 66 } 67 if(cnt==2){ 68 swap(pos1,pos2,x-1); 69 if(check(pos1,x)||check(pos2,x)){ 70 swap(pos1,pos2,x-1); 71 } 72 else{ 73 dfs(now+1,x+1); 74 swap(pos1,pos2,x-1); 75 } 76 swap(pos1,pos2+power[x-1],x-1); 77 if(check(pos1,x)||check(pos2,x)){ 78 swap(pos1,pos2+power[x-1],x-1); 79 } 80 else{ 81 dfs(now+1,x+1); 82 swap(pos1,pos2+power[x-1],x-1); 83 } 84 swap(pos1+power[x-1],pos2,x-1); 85 if(check(pos1,x)||check(pos2,x)){ 86 swap(pos1+power[x-1],pos2,x-1); 87 } 88 else{ 89 dfs(now+1,x+1); 90 swap(pos1+power[x-1],pos2,x-1); 91 } 92 swap(pos1+power[x-1],pos2+power[x-1],x-1); 93 if(check(pos1,x)||check(pos2,x)){ 94 swap(pos1+power[x-1],pos2+power[x-1],x-1); 95 } 96 else{ 97 dfs(now+1,x+1); 98 swap(pos1+power[x-1],pos2+power[x-1],x-1); 99 } 100 } 101 } 102 int main(){ 103 fac[0]=1;power[0]=1; 104 for(int i=1;i<=12;i++){ 105 fac[i]=fac[i-1]*i; 106 power[i]=power[i-1]<<1; 107 } 108 scanf("%d",&n); 109 num=qpower(2,n); 110 for(int i=1;i<=num;i++){ 111 scanf("%d",&a[i]); 112 } 113 dfs(0,1); 114 //for(int i=1;i<=15;i++) cout<<power[i]<<" "<<fac[i]<<endl; 115 //cout<<power[15]; 116 printf("%d",res); 117 }
丑陋得不能再丑陋的代码
一道看题解后完全自己码出来,调出来的代码,还是很高兴的。
搜索水平还是太弱了啊,考试时都不知道暴力怎么打,一定要提升搜索的水平啊
转载于:https://www.cnblogs.com/leom10/p/11156531.html
[sdoi2015]排序(搜索+剪枝优化)相关推荐
- BZOJ 3990: [SDOI2015]排序(搜索+剪枝)
[SDOI2015]排序 Description 小A有一个1-2^N的排列A[1..2^N],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1< ...
- 深度优先搜索(DFS) 总结(算法+剪枝+优化总结)
深度优先搜索(DFS) 总结(算法+剪枝+优化总结) 本文中会引用部分实例.文献资料来自不同的作者之手,由于资料整理比较困难,转载地址不在文中列举.如有侵权请联系我更换或删除!对于提供题解思路的各位大 ...
- CF915C Permute Digits(搜索+剪枝)
题目链接 题意: 给出两个正整数a,b.在十进制下重排a,构造一个不超过b的最大数,不能有前导零.允许不去重排a. 输入格式: 第一行一个数a(1<=a<=1018),第二行一个数b(1& ...
- 搜索算法-搜索的优化
一些搜索的优化方法: 1.爬山法 2.Best-First法 3.分支界限法 爬山法: 1.在深度优先搜索过程中,我们经常遇到多个节点可以拓展的情况,首先拓展哪个就需要一种方法: 2.爬山策略使用贪心 ...
- 程序员业务,微信全文搜索技术优化
一.iOS微信全文搜索技术的现状 全文搜索是使用倒排索引进行搜索的一种搜索方式.倒排索引也称为反向索引,是指对输入的内容中的每个Token建立一个索引,索引中保存了这个Token在内容中的具体位置.全 ...
- 小猫爬山 (深搜+搜索顺序优化)
翰翰和达达饲养了N只小猫,这天,小猫们要去爬山. 经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<). 翰翰和达达只好花钱让它们坐索道下山. 索道上的缆 ...
- 深度优先搜索及其优化
深度优先搜索(DFS)是最常用的搜索算法之一,俗称一条路走到黑. 在一般的搜索题中如果不是卡数据点的题目一般都可以直接用深搜来做,深搜也可以用某些题目的骗分[挑眉 在进行搜索的时候,选择一个没有被搜过 ...
- 京东搜索布局优化方法(干货)
无论是大型商家还是小商家,每天都在追求流量的增长.不管从快车个性化,活动个性化,搜索个性化,还是老客户个性化,重点都是研究搜索权重的入池时间,帮助我们启动个性化单品流量,提高转化率的方法论.今天我们重 ...
- (字母排序搜索)类似微信通讯录效果
最近刚好有要做一个聊天通讯录,有点类似微信,所以自己也把探索的总结一下,可能还要进一步优化: 不多说,先上效果图看看: 这里先说一些,要使用拼音字母转换,我们引用了第三方拼音库(pinyin4j-2. ...
- Seo搜索如何优化百度图片排名
随着互联网技术不断进步,满足了用户多样化的需求,自从2014年1月17日百度站长平台LEE发布了关于"走进读图时代"一文,已宣告搜索引擎已经从原来的文本搜索进入了图片搜索的时代,对 ...
最新文章
- Java常见的面试算法题:实现两个线程交替打印1到100的数
- java indexof int_Java Stack indexOf(Object, int)用法及代码示例
- android 数据库表格数据库数据库中,Android SQLite数据库中的表详解
- python is not allowed to run_【无法解决】PySpider的部署运行而非调试界面上RUN运行
- Python Demo 02 蒙特卡罗方法输出e
- vue sync用法
- java jvm容器_java – YARN:容器和JVM
- 长链接转短链接java_长链接生成短链接Java源码(调用百度接口)
- 史上最全SVN使用总结,建议先收藏后观看
- 二分法求数组最大最小_js-求数组的最大值和最小值
- 【Python】交互式界面创建函数
- 10 个步骤让你成为高效的 Web 开发者
- mysql对应systables_mysql5.7中的sys表详解(转)
- java怎么建立socket_Java Socket编程如何建立两者关系
- 【正则】详解python正则表达式之re.group()用法
- 哈尔滨工业大学机器人智谷_信利康5G智慧园和哈工大 机器人智谷项目当天摘牌当天动工...
- xmanager使用教程
- 【Unity】Kinect屏幕显示环境背景及人体投影
- DXP_protel2004_原理图设计基础_集成运放原理图设计学习
- SpringBoot+Vue搭建前后端分离的轻博客