zoukankan      html  css  js  c++  java
  • 【编程题目】12 个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,

    80.阿里巴巴一道笔试题(运算、算法)
    问题描述:
    12 个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,
    问排列方式有多少种?

    我的思路:输入从小到大排列的数字  把数字4个分为一组 如下:

    min **** B

    A    **** max

    其中第一个数字一定是当前最小的, 最后一个数字一定是当前最大的。 其次,设位置A 、B,这样去掉这四个数字, 问题又变成了规模小一些的同样的问题。

    关键是A和B的确定,有很多种可能,我们依次尝试,如果不满足问题的条件了,就退出来,换一个数字。

    A的大小: 最小可能是当前输入的第【2】个数字, 最大可能是当前输入的第 【len(输入数字的个数)/2 + 1】 个数字,此外,如果它左边有数字,A必须比其左边的数字大。

    B的大小:最小的可能是第【len/2】个数字,最大的可能是第【len - 1】个数字,此外,如果它右边有数字,B必须比其右边的数字小。

    收获:被if else语句搞晕了, 如果用if else 则是选择关系, 几个条件只会检查其中一个。这里检查条件是要求全部都检查,所以不能加else。

    /*
    80.阿里巴巴一道笔试题(运算、算法)
    问题描述:
    12 个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,
    问排列方式有多少种?
    start time = 19:20
    end time = 第二天 10:56
    */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define N 12
    int way[2][6]; //存储方式
    
    /*
    min ***** B
    A   ***** Max
    */
    int TwoLines(int * num, int len) //输入数字必须从小到大排列
    {
        static int ways = 0;
        if(len == 0)
        {
            ways++;
            printf("way:%d
    ", ways);
            for(int j = 0; j < 2; j++)
            {
                for(int i = 0; i < N/2; i++)
                {
                    printf("%d ", way[j][i]);
                }
                printf("
    ");
            }
        }
        int minloc = (N - len)/4;  //当前最小数字的位置
        int maxloc = (N + len)/4 - 1; //当前最大数字的位置
        way[0][minloc] = num[0];
        way[1][maxloc] = num[len - 1];
    
        int Bminloc = len / 2 - 1;  //B最小可能的取值在num数组中的位置
        int Bmaxloc = len - 2;
        int Aminloc = 1;
        int Amaxloc = len/2;
    
        
        for(int b = Bminloc; b <= Bmaxloc; b++)
        {
            for(int a = Aminloc; a <= Amaxloc; a++)
            {
                if(a == b ) //数字不能相同
                {
                    continue;
                }
                if(maxloc < N/2 - 1)  //b位置的数字必须比它右边的数字小
                {
                    if( !(num[b] < way[0][maxloc + 1]) )
                    {
                        continue;
                    }
                }
                if(minloc > 0) //a位置的数字必须比它左边的大
                {
                    if( !( num[a] > way[1][minloc - 1]))
                    {
                        continue;
                    }
                }
    
                way[0][maxloc] = num[b];
                way[1][minloc] = num[a];
                int * num2 = (int *)malloc((len - 4) * sizeof(int));
                int i, j;
                for(i = 1, j = 0; j < len - 4; i++)
                {
                    if(i == b || i == a)
                    {
                        continue;
                    }
                    num2[j] = num[i];
                    j++;
                }
    
                TwoLines(num2, len - 4);
                    
                free(num2);
    
        
            }
        }
        return ways;
    }
    
    int main()
    {
        int num[N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
        int ways = TwoLines(num, N);
        return 0;
    }

    网上找到了一个非常好的解法:

    http://blog.csdn.net/hackbuteer1/article/details/7450250

    虽然与卡特兰数的关系没有看懂,但是解法看懂了。很有启发性 重点看。 尤其是其中二进制的应用。

    另附一个讲解二进制很好的博客:http://www.cnblogs.com/xianghang123/archive/2011/08/24/2152408.html

    //网上答案 http://blog.csdn.net/hackbuteer1/article/details/7450250
    #include <iostream>
    using namespace std;
    
    int bit_cnt(int n)
    {
        int result = 0;
        for (; n; n &= n-1, ++result);  //统计n中 1的个数  每次把最低位的1清零
        return result;
    }
    
    int main(void)
    {
        int F[6], B[6];
        int i,j,k,state,ok,ans = 0;
        for (state = 0; state < (1 << 12); ++state)
        {
            if (bit_cnt(state) == 6)
            {
                i = j = 0;
                for (int k = 0; k < 12; ++k)
                {
                    if(state&(1<<k))  //判断对应位是否为1
                        F[i++] = k;
                    else
                        B[j++] = k;
                }
                ok = 1;
                for (k = 0; k < 6; ++k)
                {
                    if (B[k] < F[k])   //B和F分别是从小到大排的 只要检查对应位置的相对大小是否符合要求即可
                    {
                        ok = 0;
                        break;
                    }
                }
                ans += ok;
            }
        }
        cout << ans << endl;
        return 0;
    }
  • 相关阅读:
    Oracle SQL语句收集
    SqlParameter In 查询
    SQL 性能优化
    Entity Framework
    【XLL API 函数】 xlfSetName
    【XLL API 函数】xlfUnregister (Form 2)
    【XLL API 函数】xlfUnregister (Form 1)
    【Excel 4.0 函数】REGISTER 的两种形式以及VBA等效语句
    【Excel 4.0 函数】REGISTER
    【Bochs 官方手册翻译】 第一章 Bochs介绍
  • 原文地址:https://www.cnblogs.com/dplearning/p/3896708.html
Copyright © 2011-2022 走看看