PTA 1 选座位

已知公交车中有n排座位,每排都有2个座位。第i排的两个座位的宽度均为wi厘米。没有相同宽度的两排座位。

公共汽车最初是空的。有2n位乘客按顺序先后进入公共汽车。 乘客分为两种类型:

内向者:总是选择两个座位都没人的一排。在这些排中,他选择座位宽度最小的,并占据了其中的一个座位; 外向型:总是选择有人的一排。 在这些排中,他选择座位宽度最大的那个,并占据了空位。

你会得到每排座位的宽度和乘客进入公共汽车的顺序。 请你帮忙确定每位乘客将乘坐哪一排座位。

输入格式:

第一行包含一个整数n(1 ≤ n ≤ 200),表示公共汽车上座位的总排数。

第二行是一个包含n个整数的序列w 1,w 2,...,w n(1 ≤ w i ≤ 10000),其中wi是第i行中每个座位的宽度。 保证所有 w i 都不同。

第三行包含一个长度为 2n 的字符串,由数字“0”和“1”组成,该字符串描述了乘客进入公共汽车的顺序。 如果第j个字符是 '0',那么说明第 j 个进入公共汽车的乘客是内向型的;如果第j个字符是 '1',则表示第j个进入公交车的乘客是外向型的。 保证外向者的数量等于内向者的数量(即'0'和'1'的个数均为 n),并且对于每个外向者总是有合适的行。

输出格式:

打印 2n 个整数,整数之间以空格分隔,表示乘客将坐的排。 乘客的顺序应与输入的顺序相同。

输入样例1:

2
3 1
0011

输出样例1:

2 1 1 2

输入样例2:

6
10 8 9 11 13 5
010010011101

输出样例2: 

6 6 2 3 3 1 4 4 1 2 5 5

代码 :

#include<stdio.h>


int main()
{
    int row_of_seat;    scanf("%d", &row_of_seat);
    int seat[row_of_seat+1], num_of_human = row_of_seat * 2; 
    int stack[num_of_human + 1], top = 0;  // 建立栈

    for (int i = 0; i < row_of_seat; i ++)  // 输入座位宽度
    {
        scanf("%d", &seat[i]);  
    }

    char human[num_of_human + 1];    scanf("%s", human);  // 人性格类型
    for (int i = 0; i < num_of_human; i++)
    {
        // 如果本次循环到1(外向),输出栈顶并退栈.
        if (human[i] == '1') {printf("%d ", stack[--top]);}

        // 否则就是内向的人,我们就遍历剩下空的座位找到最小宽度的然后入栈.
        else
        {
            int min = 114514, minj = 0;  // 好恶臭的min
            for (int j = 0; j < row_of_seat; j++)
            {
                if (seat[j] < min && seat[j] != -1)
                {
                    min = seat[j];
                    minj = j;
                }
            }
            printf("%d ", minj + 1);  // 找到了以后先输出这个人坐的位置.
            stack[top++] = minj + 1;
            seat[minj] = -1;  // 这里把有人的座位宽度改成-1来标志已经有人坐了.
        }
    }
    return 0;
}

总结:

        这道题分析清楚后其实就是一道关于栈的题目。

        我们注意到内向的人只会坐在没人坐的位置,而外向的人只会坐在有人的位置,因此每一排都是内向的人和外向的人匹配,不会出现两个内向、外向的人坐在一起的情况。并且内向的人总是挑最窄的坐,外向的人总是挑最宽的坐。

        因此,我们建立一个栈,每次遇到内向的人就找当前无人的最小的位置入栈,就能保证栈顶的座位宽度是栈内最大。遇到外向的人就输出栈顶并退栈(栈内的位子都是有一个内向的人坐并且宽度最大)就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值