[BZOJ3990]:[SDOI2015]排序(搜索)
题目传送门
题目描述
小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认为两个操作序列不同,当且仅当操作个数不同,或者至少一个操作不同(种类不同或者操作位置不同).
下面是一个操作事例:
N=3,A[1..8]=[3,6,1,2,7,8,5,4].
第一次操作,执行第3种操作,交换A[1..4]和A[5..8],交换后的A[1..8]为[7,8,5,4,3,6,1,2].
第二次操作,执行第1种操作,交换A[3]和A[5],交换后的A[1..8]为[7,8,3,4,5,6,1,2].
第三次操作,执行第2中操作,交换A[1..2]和A[7..8],交换后的A[1..8]为[1,2,3,4,5,6,7,8].
有关题目描述的说明
说实话,一开始真没看懂题。
其实,大致意思就是说,每次把序列分成${2}^{N-i+1}$个长度为${2}^{i-1}$的块,每次可以选择其中两块交换。
需要注意的两点就是:
1.每种操作只能使用一次。
2.不是说所有长度为2(i-1)的都行,举个例子:假设长度为2,那么每一块就是{1,2},{3,4},{5,6},……,而{2,3},{4,5}则不是。
输入格式
第一行,一个整数N
输出格式
一个整数表示答案
样例
样例输入:
3
7 8 5 6 1 2 4 3
样例输出:
6
数据范围与提示
对于30%的数据,1≤N≤4; 对于全部的数据,1≤N≤12。
题解
这道题居然是搜索,简直难以置信,没办法,那就搜吧。
数据范围1≤N≤12,算一算发现是4096->5000,下意识${N}^{2}$。
首先,我们来考虑这样一个问题,如果我们执行的操作是3,1,2能完成排序,那么1,2,3也一定能,那么就是说,如果我们找到了一种操作数为x的方案,那么它对答案的贡献就是x!。
然后,再来考虑,因为每一种操作只能执行一次,所以这时候分以下四种情况:
1.没有长度为2(i-1)的不符合顺序的序列对,那么直接尝试下一种操作。例:每一块的长度为4,序列为{1,3,2,4,5,6,7,8},{3,2}虽然不符合顺序,当前操作不能对它进行操作,那么我们执行下一个操作。
2.存在一个这样的序列对,那么我们尝试进行内部交换。
3.存在两个这样的序列对,例如:每一块的长度为2,序列为{1,2,7,8,5,6,3,4},那么我们需要枚举四种情况,分别是{1,2}与{5,6}换,{1,2}与{3,4}换,{7,8}与{5,6}换,{7,8}与{3,4}换。
4.如果存在多于两个这样的序列对,那么这种方案一定行不通,赶快return就好了。
交换的时候暴力swap即可。
最后,大家可能还是毫无头绪,那么我再来解释一个问题。
我们在进行搜索的时候要从小往大搜索,因为这样,我们在交换两个长度更长的序列的时候已经保证了它里面是有序的,然后如果往后的操作可以将当前可以完成当前操作也可以完成的排序,那么就交给以后处理,例:当前每一块的为1,序列为{7,8,5,6,1,2,4,3},我们发现{7,8}和{5,6}在以后的操作中可以完成交换,那么我们现在就只尝试交换{4,3}。
统计答案时,将每一种方案的答案累加即可。
代码时刻
#include<bits/stdc++.h>
using namespace std;
int n,sum,miao;
int jc[13];
int ans;
int a[4097];
void change(int x,int y,int w){do swap(a[x+w],a[y+w]);while(w--);}//暴力swap
void dfs(int x,int w)
{
if(x==miao)//所有操作都已经尝试过了
{
ans+=jc[w];//记着加的是阶乘
return;
}
int cnt=0;
int flag[2]={0,0};//一定要是局部变量,100->25
int wzc=1<<x;//记算长度
for(int i=1;i<=n;i+=(wzc<<1))//统计位置,(wzc<<1)即为自动越过下一种操作可以处理掉的情况
{
if(a[i+wzc-1]+1!=a[i+wzc])
{
if(cnt==2)return;//如果两个以上就return
flag[cnt++]=i;
}
}
switch(cnt)
{
case 0://不存在
{
dfs(x+1,w);
return;
}
case 1://存在一对
{
change(flag[0],flag[0]+wzc,wzc-1);
dfs(x+1,w+1);
change(flag[0],flag[0]+wzc,wzc-1);
return;
}
case 2://存在两对,再分四种情况
{
if(a[flag[0]+wzc-1]+1==a[flag[1]+wzc]&&a[flag[0]+wzc]==a[flag[1]+wzc-1]+1)//先看看交换之后符不符合
{
change(flag[0],flag[1],wzc-1);
dfs(x+1,w+1);
change(flag[0],flag[1],wzc-1);
change(flag[0]+wzc,flag[1]+wzc,wzc-1);
dfs(x+1,w+1);
change(flag[0]+wzc,flag[1]+wzc,wzc-1);
}
if(a[flag[0]+wzc]-1==a[flag[1]+wzc*2-1]&&a[flag[0]]==a[flag[1]+wzc-1]+1)
{
change(flag[0],flag[1]+wzc,wzc-1);
dfs(x+1,w+1);
change(flag[0],flag[1]+wzc,wzc-1);
}
if(a[flag[1]+wzc]-1==a[flag[0]+wzc*2-1]&&a[flag[1]]==a[flag[0]+wzc-1]+1)
{
change(flag[0]+wzc,flag[1],wzc-1);
dfs(x+1,w+1);
change(flag[0]+wzc,flag[1],wzc-1);
}
return;
}
}
}
int main()
{
scanf("%d",&n);
miao=n;
jc[0]=1;
for(int i=1;i<=n;i++)
jc[i]=jc[i-1]*i;//预处理阶乘
n=1<<n;//现在n变为了序列长度了
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
dfs(0,0);//开搜
cout<<ans<<endl;
return 0;
}
rp++
[BZOJ3990]:[SDOI2015]排序(搜索)的更多相关文章
- [bzoj3990][SDOI2015]排序-搜索
Brief Description 小A有一个1-2^N的排列A[1..2^N],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1<=i<= ...
- BZOJ 3990: [SDOI2015]排序 [搜索]
3990: [SDOI2015]排序 题意:\(2^n\)的一个排列,给你n种操作,第i种把每\(2^{i-1}\)个数看成一段,交换任意两段.问是这个序列有序的操作方案数,两个操作序列不同,当且仅当 ...
- [BZOJ3990][SDOI2015]排序(DFS)
3990: [SDOI2015]排序 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 902 Solved: 463[Submit][Status][ ...
- BZOJ3990 [SDOI2015]排序 【搜索】
题目 小A有一个1-2^N的排列A[1..2^N],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1<=i<=N),第i中操作为将序列从左到 ...
- Bzoj3990 [SDOI2015]排序
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 651 Solved: 338 Description 小A有一个1-2^N的排列A[1..2^N], ...
- BZOJ 3990 [SDOI2015]排序 ——搜索
[题目分析] 可以发现,操作的先后顺序是不影响结果的,那么答案就是n!的和. 可以从小的步骤开始搜索,使得每一个当前最小的块都是上升的数列,然后看看是否可行即可. 复杂度好像是4^n [代码](哪里写 ...
- BZOJ 3990: [SDOI2015]排序(搜索+剪枝)
[SDOI2015]排序 Description 小A有一个1-2^N的排列A[1..2^N],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1< ...
- 006-筛选分类排序搜索查找Filter-Classificatio-Sort-Search-Find-Seek-Locate
006-筛选分类排序搜索查找Filter-Classificatio-Sort-Search-Find-Seek-Locate https://www.cnblogs.com/delphixx/p/1 ...
- 【LG3322】[SDOI2015]排序
[LG3322][SDOI2015]排序 题面 洛谷 题解 交换顺序显然不影响答案,所以每种本质不同的方案就给答案贡献次数的阶乘. 从小往大的交换每次至多\(4\)中决策,复杂度\(O(4^n)\). ...
随机推荐
- 洛谷 P1578 奶牛浴场 题解
题面 1.定义有效子矩形为内部不包含任何障碍点且边界与坐标轴平行的子矩形.如图所示,第一个是有效子矩形(尽管边界上有障碍点),第二个不是有效子矩形(因为内部含有障碍点). 2.极大有效子矩形:一个有效 ...
- Spring jar包详解(转)
spring.jar是包含有完整发布的单个jar包,spring.jar中包含除了spring-mock.jar里所包含的内容外其它所有jar包的内容,因为只有在开发环境下才会用到spring-moc ...
- mysql 加密 解密函数
select HEX(AES_ENCRYPT('你好世界','ABC123456')) select AES_DECRYPT(UNHEX('E85A104B6142A7375E53C0545C ...
- Python 入门之 内置模块 -- sys模块
Python 入门之 内置模块 -- sys模块 1.sys模块 sys模块是与python解释器交互的一个接口 print(sys.path) #模块查找的顺序 print(sys.argv) # ...
- java 导出自定义样式excel
由于项目需要 要求导出一个这样的表格 然而 正常导出的表格都是这样婶儿地 这种格式网上demo有很多就不详细说了 ,主要说说上面三行是怎么画的. 第一行大标题,是9行合并成的一行,而且字体大小需要单独 ...
- vue项目1-pizza点餐系统4-二级、三级路由
一.目标样式 二.二级路由 在“关于我们”(about)下面设置二级路由. 1.创建组件,在router文件夹中index.js中先导入组件,配置好路由的访问地址,名称. //二级路由 import ...
- python变量、对象和引用你真的明白了吗
python变量.对象和引用你真的明白了吗 变量.对象和引用 Python不像C++,Java等语言一样,他们可以不用事先声明变量类型而直接对变量进行赋值.对Python语言来讲,对象的类型和内存都是 ...
- kickstart一键装机部署
1.第一步安装DHCP yum -y install dhcp 1.1配置修改文件 cat >> /etc/dhcp/dhcpd.conf <<END subnet 172.1 ...
- lnmp 中的laravel出现白屏的处理办法
find / |grep fastcgi_params 其实是找fastcgi_params这个文件编辑 如果在知道目录的情况下也可以直接 vi /usr/local/nginx/conf/fastc ...
- Wiki 安装部署
#首先登陆进入 MySQL 数据库 [root@oldboy tools]# mysql -uroot -poldboy123 #创建一个 wiki 是库 mysql> create datab ...