【編程題目】12 個高矮不一樣的人,排成兩排,每排必須是從矮到高排列,並且第二排比對應的第一排的人高,

80.阿里巴巴一道筆試題(運算、算法)
問題描述:
12 個高矮不一樣的人,排成兩排,每排必須是從矮到高排列,並且第二排比對應的第一排的人高,
問排列方式有多少種?html

 

 

個人思路:輸入從小到大排列的數字  把數字4個分爲一組 以下:ios

min **** B算法

A    **** max數組

其中第一個數字必定是當前最小的, 最後一個數字必定是當前最大的。 其次,設位置A 、B,這樣去掉這四個數字, 問題又變成了規模小一些的一樣的問題。spa

關鍵是A和B的肯定,有不少種可能,咱們依次嘗試,若是不知足問題的條件了,就退出來,換一個數字。.net

A的大小: 最小多是當前輸入的第【2】個數字, 最大多是當前輸入的第 【len(輸入數字的個數)/2 + 1】 個數字,此外,若是它左邊有數字,A必須比其左邊的數字大。code

B的大小:最小的多是第【len/2】個數字,最大的多是第【len - 1】個數字,此外,若是它右邊有數字,B必須比其右邊的數字小。htm

 

收穫:被if else語句搞暈了, 若是用if else 則是選擇關係, 幾個條件只會檢查其中一個。這裏檢查條件是要求所有都檢查,因此不能加else。blog

/*
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\n", ways);
        for(int j = 0; j < 2; j++)
        {
            for(int i = 0; i < N/2; i++)
            {
                printf("%d ", way[j][i]);
            }
            printf("\n");
        }
    }
    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;
}
相關文章
相關標籤/搜索