美团笔试 2023-3-11

 

第一题:字符串修改

题目描述

小美有一个由数字字符组成的字符串。现在她想对这个字符串进行一些修改。

具体地,她可以将这个字符串中任意位置字符修改为任意的数字字符。

她想知道,至少进行多少次修改,可以使得修改后的字符串不包含两个连续相同的字符?

例如,对于字符串”111222333”。她可以进行3次修改将其变为”121212313。

输入描述

一行,一个字符串s,保证s只包含数字字符。1<=|s|<=100000

  • 111222333

输出描述

一行,一个整数,表示修改的最少次数。

  • 3

个人解法

#include<stdio.h>
#include<iostream>

using namespace std;

int mod(string s) {
    int num=0;
    if (s.size() < 2) return 0;
    for (int i = 1; i < s.size()-1; i++) {
        if (s[i] == s[i - 1]) {
            s[i] = max(s[i + 1], s[i - 1]) + 1;
            num++;
        }
    }
    if (s[s.size() - 1] == s[s.size() - 2]) num++;
    return num;
}
int main() 
{
    string s;
    cin >> s;
    cout<<mod(s);
    return 0;
}

 

第二题:最优规划

题目描述

小团在一个n*m的网格地图上探索。网格地图上第i行第j列的格子用坐标(ij)简记。初始时,小团的位置在地图的左上角,即坐标(1,1)。地图上的每一个格子上都有一定的金币,特别地,小团位于的初始位置(1,1)上的金币为0。小团在进行探索移动时,可以选择向右移动一格(即从(x,y)到达(x,y+1))或向下移动一格(即从(x,y)到达(x+1,y)))。地图上的每个格子都有一个颜色,红色或蓝色。

如果小团一次移动前后的两个格子颜色不同,那么他需要支付k个金币才能够完成放一次移动;如果移动前后的两个格子颜色相同,则不需要支付金币。小团可以在任意格子选择结束探索。

现在给你网格地图上每个格子的颜色与金币数量,假设小团初始时的金币数量为0,请你帮助小团计算出最优规划,使他能获得最多的金币,输出能获得的最多金币数量即可。

注意:要求保证小团任意时刻金币数量不小于零。

输入描述

第一行是三个用空格隔开的整数n、m和k,表示网格地图的行数为n,列数为m,在不同颜色的两个格子间移动需要支付k个金币。

接下来n行,每行是一个长度为m的字符串,字符串仅包含字符’R’或’B’。第i行字符串的第j个字符表示地图上第i行第j列的格子颜色,如果字符为’R’则表示格子颜色为红色,为’B’表示格子颜色为蓝色。

接下来是一个n行m列的非负整数矩阵,第i行第j列的数字表示地图上第i行第j列的格子上的金币数量。保证所有数据中数字大小都是介于[0,10]的整数。

1<=n,m<=200,1<=k<=5。

  • 1 7 2
  • BBRBRBR
  • 0 3 2 4 1 1 1

输出描述

一行一个整数,表示小团能获得的最多金币数量。

  • 5

样例解释

小团先从(1,1)移动到(1,2),获得3个金币;

再从(1,2)移动到(1,3),需要先支付2个金币,然后获得2个金币,此时持有3个金币;再从(1,3)移动到(1,4),需要先支付2个金币,然后获得4个金币,此时持有5个金币;然后结束探索,最终获得5个金币。

如果继续向右走,每一步都需要支付2个金币,但只获得1个金币,因此在(1,4)结束是最优的。

个人解法

使用动态规划法

#include<stdio.h>
#include<iostream>
#include<vector>

using namespace std;

int getmaxgold(int n,int m,int k,vector<string>vec, vector<vector<int>> gold) {
    int maxgold = 0;//更新最大值
    vector<vector<int>>dp(n, vector<int>(m));//保存动规结果
    //dp初始化
    dp[0][0] = 0;
    if(n>1) dp[1][0] = gold[1][0] - ((vec[0][0] == vec[1][0]) ? 0 : k);
    if(m>1) dp[0][1] = gold[0][1] - ((vec[0][0] == vec[0][1]) ? 0 : k);
    if (n == 1) {//只有一行
        for(int j=1;j<m;j++){
            dp[0][j] = gold[0][j] + dp[0][j - 1] - ((vec[0][j] == vec[0][j - 1]) ? 0 : k);
            maxgold = max(maxgold, dp[0][j]);
        }
    }
    if (m == 1) {//只有一列
        for (int i = 1; i < n; i++) {
            dp[i][0] = gold[i][0] + dp[i - 1][0] - ((vec[i][0] == vec[i - 1][0]) ? 0 : k);
            maxgold = max(maxgold, dp[i][0]);
        }
    }
    for (int i = 1; i < n; i++) {
        for (int j = 1; j < m; j++) {
            dp[i][j] = max(dp[i][j - 1] - ((vec[i][j] == vec[i][j - 1]) ? 0 : k), dp[i-1][j] - ((vec[i][j] == vec[i-1][j ]) ? 0 : k)) + gold[i][j];
            maxgold = max(maxgold, dp[i][j]);
        }
    }
    return maxgold;
}
int main() 
{
    int n, m, k;//n行m列k金币
    cin >> n >> m >> k;
    vector<string>vec;//保存颜色字符串
    string s;//颜色字符串
    for (int i = 0; i < n; i++) {
        cin >> s;
        vec.push_back(s);
    }
    int goldi;
    vector<vector<int>> gold(n,vector<int>(m));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> goldi;
            gold[i][j] = goldi;
        }
    }
    cout << getmaxgold(n, m, k, vec, gold);
    return 0;
}

个人增加样例

输入:

  • 2 2 2
  • BB
  • RR
  • 0 2
  • 3 1

输出:

  • 2

第三题:流星

题目描述

小美是一位天文爱好者,她收集了接下来一段时间中所有会划过她所在的观测地上空的流星信息。

具体地,她收集了n个流星在她所在观测地上空的出现时刻和消失时刻。对于一个流星,若其的出现时刻为s,消失时刻为t,那么小美在时间段[s, t]都能够观测到它。对于一个时刻,观测地上空出现的流星数量越多,则小美认为该时刻越好。小美希望能够选择一个最佳的时刻进行观测和摄影,使她能观测到最多数量的流星。

现在小美想知道,在这个最佳时刻,她最多能观测到多少个流星以及一共有多少个最佳时刻可供她选择。

输入描述

第一行是一个正整数n,表示流星的数量。

第二行是n个用空格隔开的正整数,第i个数si表示第i个流星的出现时间。第三行是n个用空格隔开的正整数,第i个数ti表示第i个流星的消失时间。1<=n<=100000,1<=si<=ti<=10^9

  • 3
  • 2 1 5
  • 6 3 7

3

2 1 5

6 3 7

输出描述

输出一行用空格隔开的两个数x和y,其中x表示小美能观测到的最多流星数,y表示可供她选择的最佳时刻数量

  • 2 4

样例解释

在7个时刻中,时刻2、3、5、6可以观测到2个流星,其他时刻只能观测到1个流星。所以最多能观测到的流星数量为2,最佳时刻的数量是4。

个人解法

排序

#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int main() 
{
    int n;//流星数量
    cin >> n;
    int num;
    vector<pair<int, int>>star;
    for (int i = 0; i < n; i++) {
        cin >> num;
        star.push_back(pair<int, int>(num, 0));//开始为0
    }
    for (int i = 0; i < n; i++) {
        cin >> num;
        star.push_back(pair<int, int>(num, 1));//结束为1
    }
    int bestnum=0;//最佳观测数量
    int starnum=0;//此时流星数量
    int startime = 0;//最佳观测时间段数量
    sort(star.begin(), star.end());
    int last = star[2 * n - 1].first;//最后一个时刻
    vector<int>record(last+1,-1);//每个时刻星星数量
    for (auto s : star) {
        if (s.second == 0) starnum++;//开始,星星数量加一
        record[s.first] = starnum;
        if (s.second == 1) {//结束,星星数量减一
            starnum--;
            if(s.first!=last) record[s.first + 1] = starnum;//下一个时刻的星星数量是减1后
        }
        bestnum = max(bestnum, starnum);
    }
    if(record[0]==-1) record[0] = 0;
    for (int i = 1; i < last; i++) {
        if (record[i] == -1) record[i] = record[i - 1];
        if (record[i] == bestnum) startime++;
    }
    cout << bestnum<<" "<<startime;
    return 0;
}

力扣类似题目

#2251  花期内花的数目

 

第四题:坦克大战

题目描述

小D和小W最近在玩坦克大战,双方操控自己的坦克在16*16的方格图上战斗,小D的坦克初始位置在地图的左上角,朝向为右,其坐标(0,0),小W的坦克初始位置在地图右下角,朝向为左,坐标为(15,15)。坦克不能移动到地图外,坦克会占领自己所在的格子,己方的坦克不可以进入对方占领过的格子。每一个回合双方必须对自己的坦克下达以下5种指令中的一种:

  • 移动指令U:回合结束后,使己方坦克朝向为上,若上方的格子未被对方占领,则向当前朝向移动一个单位(横坐标-1),否则保持不动;
  • 移动指令D:回合结束后,使己方坦克朝向为下,若下方的格子未被对方占领,则向当前朝向移动一个单位(横坐标+1),否则保持不动;
  • 移动指令L:回合结束后,使己方坦克朝向为左,若左侧的格子未被对方占领,则向当前朝向移动一个单位(纵坐标-1),否则保持不动;
  • 移动指令R:回合结束后,使己方坦克朝向为右,若右侧的格子未被对方占领,则向当前朝向移动一个单位(纵坐标+1),否则保持不动;
  • 开火指令F:己方坦克在当前回合立即向当前朝向开火;

己方坦克开火后,当前回合己方坦克的正前方若有对方的坦克,对方的坦克将被摧毁,游戏结束,己方获得胜利;若双方的坦克在同一回合被摧毁,游戏结束,判定为平局;若双方的坦克在同一回合内进入到同一个未被占领的格子,则双方的坦克发生碰撞,游戏结束,判定为平局;当游戏进行到第256个回合后,游戏结束,若双方坦克均未被摧毁,则占领格子数多的一方获得胜利,若双方占领的格子数一样多,判定为平局。注意,若一方开火,另一方移动,则认为是先开火,后移动。

现在小D和小W各自给出一串长度为256的指令字符串,请你帮助他们计算出游戏将在多少个回合后结束,以及游戏的结果。

输入描述

输入共两行,每行为一串长度为256的指令字符串,字符串中只包含"U" .“D”,“L”“R”,“F”这五个字符。第一行表示小D的指令,第二行表示小W的指令。

  • RRRRRRRRDDDDDDDDDRFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
  • UUUUUUUULFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

输出描述

输出一共两行:

第一行一个整数k,表示游戏将在k个回合后结束。

第二行为游戏的结果,若小D获胜则输出“D”,若小W获胜则输出“W”,若平局则输出“P”。

  • 16
  • W

样例解释

第8回合结束后,小w的坐标为(7,14),方向朝左,此后每个回合都在开火;小D在第15个回合结束后到达坐标(7,8),在第16回合,小p发出移动指令D,小w发出开火指令F,小D的坦克被摧毁,小w获得胜利。

个人解法

#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
#include<map>

using namespace std;

int main() 
{
    string d, w;
    cin >> d >> w;
    int map[16][16] = { 0 };
    int num = 0;//回合数
    map[0][0] = 1;//小D最初在左上角
    map[15][15] = 2;//小W最初在右下角
    char Ddirection = 'R', Wdirection = 'L';//最初朝向
    int dx = 0, dy = 0, wx = 15, wy = 15;//坐标
    int Ddeath = 0, Wdeath = 0;
    int numd = 0,numw = 0;
    for (int i = 0; i < 256; i++) {
        if (d[i] == 'F') {
            if (Ddirection == 'U' && dy == wy && dx > wx) Wdeath = 1;
            else if (Ddirection == 'D' && dy == wy && dx < wx) Wdeath = 1;
            else if (Ddirection == 'L' && dx == wx && dy > wy) Wdeath = 1;
            else if (Ddirection == 'R' && dx == wx && dy < wy) Wdeath = 1;
        }
        if (w[i] == 'F') {
            if (Wdirection == 'U' && dy == wy && dx < wx) Ddeath = 1;
            else if (Wdirection == 'D' && dy == wy && dx > wx) Ddeath = 1;
            else if (Wdirection == 'L' && dx == wx && dy < wy) Ddeath = 1;
            else if (Wdirection == 'R' && dx == wx && dy > wy) Ddeath = 1;
        }
        switch (d[i])
        {
        case 'U':
            Ddirection = 'U';
            if (map[dx - 1][dy] == 0) {
                map[dx - 1][dy] = 1;
                dx--;
                numd++;
            }
            break;
        case 'D':
            Ddirection = 'D';
            if (map[dx + 1][dy] == 0) {
                map[dx + 1][dy] = 1;
                dx++;
                numd++;
            }
            break;
        case 'L':
            Ddirection = 'L';
            if (map[dx][dy-1] == 0){
                map[dx][dy - 1] = 1;
                dy--;
                numd++;
            }
            break;
        case 'R':
            Ddirection = 'R';
            if (map[dx][dy + 1] == 0) {
                map[dx][dy + 1] = 1;
                dy++;
                numd++;
            }
            break;
        default:
            break;
        }
        switch (w[i])
        {
        case 'U':
            Wdirection = 'U';
            if (map[wx - 1][wy] == 0) {
                map[wx - 1][wy] = 2;
                wx--;
                numw++;
            }
            break;
        case 'D':
            Wdirection = 'D';
            if (map[wx + 1][wy] == 0) {
                map[wx + 1][wy] = 2;
                wx++;
                numw++;
            }
            break;
        case 'L':
            Wdirection = 'L';
            if (map[wx][wy - 1] == 0) {
                map[wx][wy - 1] = 2;
                wy--;
                numw++;
            }
            break;
        case 'R':
            Wdirection = 'R';
            if (map[wx][wy + 1] == 0) {
                map[wx][wy + 1] = 2;
                wy++;
                numw++;
            }
            break;
        default:
            break;
        }
        if (Ddeath == 1 && Wdeath == 1) {
            cout << i + 1 << endl << 'P';
            return 0;
        }
        if (Ddeath == 1) {
            cout << i + 1 << endl << 'W';
            return 0;
        }
        else if (Wdeath == 1) {
            cout << i + 1 << endl << 'D';
            return 0;
        }
        if (dx == wx && dy == wy) {
            cout << i + 1 << endl << 'P';
            return 0;
        }
    }
    if (numd > numw) cout << "256" << endl << "D";
    else if (numd < numw) cout << "256" << endl << "W";
    else cout << "256" << endl << "P";
    return 0;
}

个人增加样例

输入:

  • RFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
  • FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

输出:

  • 256
  • D

输入:

  • RFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
  • LFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

输出:

  • 256
  • P

第五题:平衡点

题目描述

給一棵有n个点的有根树,点的编号为1到n,根为1,。每个点的颜色是红色或者蓝色,对于树上的一个点,如果其子树中(不包括该点本身)红色点和蓝色点的数量相同,那么我们称该点是平衡的。请你计算给定的树中有多少个点是平衡点

输入描述

第一行是一个正整数n,表示有n个点

接下来一行一个长度为n的字符串,仅包含字符R和B,第i个字符表示编号为i的节点的颜色,R红色,B蓝色

接下来一行n-1个用空格隔开的整数,第i个整数表示编号为i+1的点的父亲节点的编号

1<=n<=10000

输出描述

一行一个整数,表示树上平衡点的个数

题目来源参考博客:

https://blog.csdn.net/weixin_41896265/article/details/129470681?spm=1001.2014.3001.5501

posted @ 2023-03-24 14:34  feifei102  阅读(237)  评论(0)    收藏  举报