校招笔试题-玩转南美馆

原题描述:

世博会期间,小明计划玩遍所有南美国家馆,南美共有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;
    }
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值