zoukankan      html  css  js  c++  java
  • 【火车出栈】ZOJ

    好久没写递归了,怕手生再来练练手。

    题意:车轨上有上图所示的n个中转栈,现有2n个列车,给出列车初始编号序列。列车从最右边驶入车轨,并且列车只能从右向左移动,要求给出列车中转操作序列,使列车经过这n个中转栈后从最左端输出时满足1~2n的排列。

    分析:其实这不就是火车出栈问题吗,可以用分治递归的思路,首先使一半有序,然后再合并使整体有序。

    思路:具体来讲就是,一段无序的序列(编号1~2n),通过一个中转栈使1 ~ 2n-1在整个序列的前面2n-1+1 ~ 2n在整个序列的后面;再经过下一中转栈时,又能进一步进行排序,这样在最后一个中转栈是就只是两两之间的有序无序问题了。

    什么都不如例子来的好使,比如n=3时,初始序列为 2 1 5 8 7 3 6 4

    经过栈1时,使序列满足如下形式:2 1 3 4 | 6 7 8 5

    经过栈2时,使序列满足如下形式:2 1 | 3 4 | 6 5 | 8 7

    经过栈3时,使序列满足如下形式:1 2 | 3 4 | 5 6 | 7 8

    然后就达到要求了。

    那么该如何操作才能达到上述状态呢?

    比如经过栈1时,可将序列分成包含(1~4)和(5~8)的两段子序列。那么每来一个数,判断该数是否大于4,若小于等于4,则该列车进栈接着出栈;否则该列车暂时停放在栈中,等所有小于等于4的列车出栈后再按照先进后出的性质出栈,这样就达到了目的;

    经过栈1时的操作序列:2 2 1 1 5 8 7 3 3 6 4 4 6 7 8 5

    经过下面的栈的情况就类似了,不再赘述了。

    附代码:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <cstdio>
     5 #include <stack>
     6 using namespace std;
     7 const int maxn = 5000;
     8 int a[maxn];
     9 void dfs(int num[], int r, int k)
    10 {
    11     if(k <= 1)  return ;
    12     int s1[k/2 + 1];
    13     int s2[k/2 + 1];
    14     int k1 = 0, k2 = k/2;
    15     int l = r-k;
    16     int mid = (l + r)/2;
    17 
    18     stack<int> si;
    19     int p1, p2; p1 = p2 = 0;
    20     for(int i = 0; i < k; i++)
    21     {
    22         if(num[i] <= mid)
    23         {
    24             s1[p1++] = num[i];
    25             printf("%d %d ", num[i], num[i]);
    26         }
    27         else
    28         {
    29             printf("%d ", num[i]);
    30             si.push(num[i]);
    31         }
    32     }
    33     while(!si.empty())
    34     {
    35         s2[p2] = si.top();
    36         printf("%d ", s2[p2++]);
    37         si.pop();
    38     }
    39     dfs(s1, mid, k/2);
    40     dfs(s2, r, k/2);
    41     return ;
    42 }
    43 
    44 
    45 int main()
    46 {
    47     int n;
    48     while(~scanf("%d", &n) && n)
    49     {
    50         int m = 1<<n;
    51         for(int i = 0; i < m; i++)
    52             scanf("%d", &a[i]);
    53         dfs(a, m, m);
    54         printf("
    ");
    55     }
    56     return 0;
    57 }
    View Code
  • 相关阅读:
    Axure高保真开关交互效果
    Axure工具栏展开关闭交互效果
    Axure跑马灯交互效果
    for循环实现百钱买百鸡的问题: 公鸡5元一只,母鸡3元一只,小鸡1元3只,100元要买100只鸡?有多少买法?
    git的几种撤销提交方式
    react父子组件之间传值
    pm2 常用命令
    Dva.js 入门级教学文档-2
    Dva.js 入门级教学文档-1
    深入理解call函数
  • 原文地址:https://www.cnblogs.com/LLGemini/p/4740531.html
Copyright © 2011-2022 走看看