1. 程式人生 > >校招筆試題-玩轉南美館

校招筆試題-玩轉南美館

原題描述:

世博會期間,小明計劃玩遍所有南美國家館,南美共有10個國家,按順序編號分別為0-9. 
小明的遊玩方案是這樣的: 
若玩的人太多,就把館分成兩批,分的方式是在相鄰的某兩館之間插一個牌子:任選其中一批先玩,另一批後玩; 
若一批館還是玩不玩,則繼續分為兩批,且一批中的館全部玩完之後才能玩下一批館; 
每批館玩的時候,只能從這批當中編號最小的館開始,按照相鄰的編號逐個玩,一天至少可以玩一個館。 
十個館玩遍之後,小明拿出在是個館蓋章的冊子,請你根據冊子上蓋章的順序,判斷小明是否遵循了自己的遊玩方案。

輸入:0-9十個數字的排列;
輸出:符合規則的,輸出yes,不符合規則的,輸出no;

初一看,給我看糊塗了,一開始理解:將這些館分成十批,隨意訪問不就可以了?那哪個樣例都對啊;

關鍵語句:每批館玩的時候,只能從這批當中編號最小的館開始;一定要明白

首先,分兩批A,B,若先訪問A,A內部無論怎麼劃分,都必須先訪問完A後,再訪問B

A,B內部也要遵循此要求;層層遞進

那麼,訪問序列可以先分成兩部分,一部分所有元素,必然都大於或小於另一部分所有元素,層層遞推;

分析到這裡:很像二叉排序樹啊,但不是哦,子樹不一定有序排列的,而且左子樹不一定大於右子樹;

樣例:

3287956401 yes
4130279856 no

按照上面的推理,就可以寫程式碼了,問題轉化為:根據輸入,否分成左右序列,左序列大於或小於右序列;

返回找到條件:滿足上述要求,直至子序列元素為1,2;否則返回false;合法輸入之類的先不說;

#include <iostream>
using namespace std;
bool test(int *a,int n)//序列指標,序列元素數
{
    if(n<=2)
        return true;
    bool rc,lc;
    int rmin,rmax,lmin,lmax;//左右序列最大最小值
    for(int i=1;i<n;i++)//序列劃分區間左[0,i),右[i,n-1];
    {
        rmin=rmax=a[0];
        lmax=lmin=a[i];
        for(int j=0;j<i;j++)
        {
            rmin>a[j]?rmin=a[j]:0;
            rmax<a[j]?rmax=a[j]:0;
        }
        for(int j=i;j<n;j++)
        {
            lmin>a[j]?lmin=a[j]:0;
            lmax<a[j]?lmax=a[j]:0;
        }
        if(!((rmax<lmin)||(rmin>lmax)))
            continue;
        rc=test(a,i);
        lc=test(a+i,n-i);
        bool flag=rc&&lc;
        if(flag)
            return true;
        else
            return false;
    }
}
int main()
{
    string s;
    int a[10]={0};
    while(cin>>s)
    {
        for(int i=0;i<10;i++)
        {
            a[i]=s[i]-'0';
        }
        bool flag=test(a,10);
        if(flag)
            cout<<"yes"<<endl;
        else
            cout<<"no"<<endl;
    }
}