zoukankan      html  css  js  c++  java
  • 【搜索】BZOJ 3990: 【Sdoi 2015】排序

    3990: [SDOI2015]排序

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 336  Solved: 164
    [Submit][Status][Discuss]

    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认为两个操作序列不同,当且仅当操作个数不同,或者至少一个操作不同(种类不同或者操作位置不同).

      下面是一个操作事例:
      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].
     

    Input

    第一行,一个整数N

    第二行,2^N个整数,A[1..2^N]
     

    Output

    一个整数表示答案

     

    Sample Input

    3
    7 8 5 6 1 2 4 3

    Sample Output

    6

      网上题解都看不懂。。
      只能%hzwer代码。
      
      黄学长:
      每种交换只能用一次。
      我们从小到大DFS,对于第i次操作我们将序列分成2^(n-i)段,每段长度2^i
      我们找到序列中不是连续递增的段,如果这样的段超过2个,显然就废了

      如果没有这样的段,就不需要执行这个操作

      如果有一个这样的段,判断将这个段的前半部分和后半部分交换后是否连续递增,如果是就交换然后继续DFS

      如果有两个这样的段,判断四种交换情况然后DFS

      

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5  
     6 using namespace std;
     7  
     8 int a[4098],n;
     9  
    10 long long fac[14],ans=0;
    11  
    12 void init(){fac[1]=1;for(int i=2;i<=n;i++)fac[i]=fac[i-1]*i;}
    13  
    14 int read()
    15 {
    16     int x=0;char ch=getchar();
    17     while(ch<'0'||ch>'9')ch=getchar();
    18     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    19     return x;
    20 }
    21  
    22 void swap(int x,int y,int nu)
    23 {
    24     for(int i=x,j=y,nn=0;nn<nu;nn++)
    25         swap(a[i+nn],a[j+nn]);
    26 }
    27  
    28 void DFS(int dep,int sco)
    29 {
    30     if(dep==n)
    31     {
    32         ans+=fac[sco];
    33         return;
    34     }
    35     int temp=1<<(dep+1),stack[4]={0,0,0,0},top=0;
    36     for(int i=1;i<(1<<n);i+=temp)
    37     {
    38         if(a[i+(temp>>1)-1]+1!=a[i+(temp>>1)])stack[++top]=i+(temp>>1)-1;
    39         if(top>2)return;
    40     }
    41     if(top==0)
    42     {
    43         DFS(dep+1,sco);
    44         return;
    45     }
    46     else if(top==1)
    47     {
    48         if(a[stack[1]-(temp>>1)+1]!=a[stack[1]+(temp>>1)]+1)return;
    49         swap(stack[top]-(temp>>1)+1,stack[top]+1,temp>>1);
    50         DFS(dep+1,sco+1);
    51         swap(stack[top]-(temp>>1)+1,stack[top]+1,temp>>1);
    52         return;
    53     }
    54     else
    55     {
    56         if(a[stack[1]]+1==a[stack[2]+1]&&a[stack[2]]+1==a[stack[1]+1])
    57         {
    58             swap(stack[1]-(temp>>1)+1,stack[2]-(temp>>1)+1,temp>>1);
    59             DFS(dep+1,sco+1);
    60             swap(stack[1]-(temp>>1)+1,stack[2]-(temp>>1)+1,temp>>1);
    61             swap(stack[1]+1,stack[2]+1,temp>>1);
    62             DFS(dep+1,sco+1);
    63             swap(stack[1]+1,stack[2]+1,temp>>1);
    64         }
    65         else if(a[stack[1]]+1==a[stack[2]-(temp>>1)+1]&&a[stack[1]+(temp>>1)]+1==a[stack[2]+1])
    66         {
    67             swap(stack[1]+1,stack[2]-(temp>>1)+1,temp>>1);
    68             DFS(dep+1,sco+1);
    69             swap(stack[1]+1,stack[2]-(temp>>1)+1,temp>>1);
    70         }
    71         else if(a[stack[2]]+1==a[stack[1]-(temp>>1)+1]&&a[stack[2]+(temp>>1)]+1==a[stack[1]+1])
    72         {
    73             swap(stack[2]+1,stack[1]-(temp>>1)+1,temp>>1);
    74             DFS(dep+1,sco+1);
    75             swap(stack[2]+1,stack[1]-(temp>>1)+1,temp>>1);
    76         }
    77         return;
    78     }
    79 }
    80  
    81 int main()
    82 {
    83     n=read();
    84     init();
    85     for(int i=1;i<=(1<<n);i++)
    86         a[i]=read();
    87     DFS(0,0);
    88     printf("%lld",ans);
    89     return 0;
    90 }
    View Code
  • 相关阅读:
    osx 编译安装配置 ruby on rails
    tls/ssl证书生成和格式转换
    nginx相关的一些记录
    用systemd脚本自动启动node js程序
    SSH Tunneling
    c代码读取目录信息
    用Qt Creator 对 leveldb 进行简单的读写
    centos 7 相关的一些记录
    发现一段精简的模板算法(非原创)
    几个常用的散列算法
  • 原文地址:https://www.cnblogs.com/tuigou/p/4838983.html
Copyright © 2011-2022 走看看