美团2021笔试通用卷08

美团2021笔试通用卷08

美团的题真的一如既往有水平 太难了

01 - 小美的暑假

小美的书架上有很多书。小美是个爱读书的新时代好青年。 小团虽然也喜欢看书,但小团大多数时候都更喜欢来小美家蹭书读。 这就导致小美的书架上很多书都会被小团借走。 小美很烦这一点,就想出了一个招数,小美的书架是一行一行的,他会对一些行加锁,这样小团就借不走了。 现在小团想要借书,请你帮忙看看小团能不能借到书,如果可以借到的话在哪一行书架上有这本书。 为了简单起见,每本书将用一个正整数进行编号,小美的书架一共有N行。


这题模拟题

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <unordered_map>
using namespace std;
int n, m, T;

vector<int> shelf;
vector<bool> isonshelf, locker, ismei;

void add(int a, int b)
{
    if(!ismei[a] ||locker[shelf[a]] || locker[b])
        return;
    isonshelf[a] = true;
    ismei[a] = true;
    shelf[a] = b;
}
void lockered(int a)
{
    locker[a] = true;
}
void unlockered(int a)
{
    locker[a] = false;
}
int borrow(int a)
{
    if(!isonshelf[a] || locker[shelf[a]]) return -1;
    isonshelf[a] = false;
    ismei[a] = false;
    int ans = shelf[a];
    shelf[a] = 0;
    return ans;
}
void getback(int a)
{
    ismei[a] = true;
}
int main()
{
    scanf("%d%d%d", &n, &m, &T);
    shelf = vector<int>(2 * n + m + 10, 0); 
    isonshelf = vector<bool>(2 * n + m + 10, false);
    ismei = vector<bool>(2 * n + m + 10, true);
    locker = vector<bool>(2 * n + m + 10, false);
    while(T--)
    {
        int op, a, b;
        scanf("%d%d", &op, &a);
        if(op == 1)
        {
            scanf("%d", &b);
            add(a, b);
        } else if (op == 2)
        {
            lockered(a);
        } else if (op == 3)
        {
            unlockered(a);
        } else if(op == 4)
        {
            cout << borrow(a) << endl;
        } 
        else if (op == 5){
            getback(a);
        }
    }
    return 0;
}

02 - 偏爱字母

小美喜欢字母E,讨厌字母F。在小美生日时,小团送了小美一个仅包含字母E和F的字符串,小美想从中选出一个包含字母E数量与字母F数量之差最大的子串。

*子串:从字符串前面连续删去若干个字符,从后面连续删去若干个字符剩下的字符串(也可以一个都不删),例如abcab是fabcab的子串,而不是abcad的子串。我们将空串看作所有字符串的子串。


最大连续子序列和 -> 最大的前缀和 和最小的前缀和之差 就是最大的连续子序列和

03 - 搭配出售

服装店新进了a条领带,b条裤子,c个帽子,d件衬衫,现在要把这些搭配起来售卖。有三种搭配方式,一条领带和一件衬衫,一条裤子和一件衬衫,一个帽子和一件衬衫。卖出一套领带加衬衫可以得到e元,卖出一套裤子加衬衫可以得到f元,卖出一套帽子加衬衫可以得到g元。现在你需要输出最大的获利方式;


这题 看起来是分组背包 实际上是多重背包 这里以衬衫的数量作为体积(因为每一组都是用到衬衫) 这里多重背包的二进制优化复习一下

04 - 十字路口

在小美和小团生活的城市中,有n行m列共计nm个十字路口,第i行j列的十字路口有两个属性aij,b­ij。当行人处在i行j列的路口,对于任意非负整数k: 当时间处在[k*aij+k*b­ij), (k+1)*aij+k*bij)时,行人可以选择走到i±1行j列的路口。 当时间处在[(k+1)*aij+k*bij), (k+1)*aij+(k+1)*b­ij)时,行人可以选择走到i行j±1列的路口。 每次移动花费的时间为1,且要保证将要去的十字路口存在,即属于nm个路口当中。可以选择原地静止不动。 在第0时刻,小美处在xs行ys列的十字路口处,要去xt行yt列的十字路口找小团。小团原地不动等小美,请问小美所花费的时间最少是多少?


哇这题真的是学到了 这题很有水平

开始以为这种带时间的最短路只能搜索(搜索的只能过40%)来着 后来发现其实并非依赖整个路程的时间 只是依赖上一个状态的时间而已-> 完全可以利用最短路的解法来做这个题 只不过路径权值并非固定 要根据从上一个状态转移来的计算

简单来说 这里的路径长度就是时间 学到了 第一次做这样的题555

如果在这个时间区间内(这里用余(ai + bi)来计算) 可以直接转移 不然就得等一会到下个区间的起点 (这里最优性应该是显然的)

这里等的时间一个是0-> 直接可以走 要么就是区间端点减去当前余值-> 最优的等待值

最短路的框架就用Dijktra好了

很有水平的一道题 最近做题学到最多的一道了(流泪)

Last updated