2024年团队程序设计天梯赛模拟赛 L1 + L2

目录

L1 - 6 剪切复制

L1 - 8 小偷踩点

L2 - 1 推宝塔

L2 - 2 含茶量

L2 - 3 到底爱不爱我

L2 - 4 寻宝图


L1 - 6 剪切复制

使用计算机进行文本编辑时常见的功能是剪切功能(快捷键:Ctrl + X)。请实现一个简单的具有剪切和粘贴功能的文本编辑工具。

工具需要完成一系列剪切后粘贴的操作,每次操作分为两步:

  • 剪切:给定需操作的起始位置和结束位置,将当前字符串中起始位置到结束位置部分的字符串放入剪贴板中,并删除当前字符串对应位置的内容。例如,当前字符串为 abcdefg,起始位置为 3,结束位置为 5,则剪贴操作后, 剪贴板内容为 cde,操作后字符串变为 abfg。字符串位置从 1 开始编号。
  • 粘贴:给定插入位置的前后字符串,寻找到插入位置,将剪贴板内容插入到位置中,并清除剪贴板内容。例如,对于上面操作后的结果,给定插入位置前为 bf,插入位置后为 g,则插入后变为 abfcdeg。如找不到应该插入的位置,则直接将插入位置设置为字符串最后,仍然完成插入操作。查找字符串时区分大小写。

每次操作后的字符串即为新的当前字符串。在若干次操作后,请给出最后的编辑结果。

输入格式:

输入第一行是一个长度小于等于 200 的字符串 S,表示原始字符串。字符串只包含所有可见 ASCII 字符,不包含回车与空格。

第二行是一个正整数 N (1≤N≤100),表示要进行的操作次数。

接下来的 N 行,每行是两个数字和两个长度不大于 5 的不包含空格的非空字符串,前两个数字表示需要剪切的位置,后两个字符串表示插入位置前和后的字符串,用一个空格隔开。如果有多个可插入的位置,选择最靠近当前操作字符串开头的一个。

剪切的位置保证总是合法的。

输出格式:

输出一行,表示操作后的字符串。s

AcrosstheGreatWall,wecanreacheverycornerintheworld
5
10 18 ery cor
32 40 , we
1 6 tW all
14 18 rnerr eache
1 1 e r

输出样例:

he,allcornetrrwecaneacheveryGreatWintheworldAcross

AC 代码

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string s;
    int n;
    cin >> s >> n;
    while (n--)
    {
        int start = 0, end = 0;
        string s1, s2;
        cin >> start >> end;
        cin >> s1 >> s2;
        start -= 1, end -= 1;
        string tmp = s.substr(start, end - start + 1);
        s.erase(start, end - start + 1);
        s2 = s1 + s2;
        if (s.find(s2) != -1) s.insert(s.find(s2) + s1.size(), tmp);
        else s+= tmp;
    }
    cout << s;
    return 0;
}

L1 - 8 小偷踩点

s.jpg

俗话说不怕贼偷,就怕贼惦记。

小偷在作案前有时会在居民家的门、墙上做一些标记,每一种记号代表一个含义,一般人看不懂,但同行一看便知道这个家庭的情况。不过派出所干警也不是吃素的,很快破译了这些记号的含义(如上图),并且在辖区内广为张贴,告知居民。

随后小偷们又改变了方法,将这些记号从 1 到 N 编号,然后将这些编号按照某种规则重新打乱再做标记,标记变成了一串数字。不过这种新的编号方法又被破译了!干警们发现这些数字的规律可以用一个二维矩阵来表示:矩阵有 10 列,顺序对应数字 0 到 9;矩阵一般不超过 10 行,每行对应一个 0 到 9 之间的数字,这些数字保证不重复。小偷的新标记由若干个两位数组成,每个数字的十位对应行、个位对应列,而对应位置上的数字就是原始标记的编号。

如上图 40 种标记从上到下、从左到右顺序编号后,按下图所示的规律打乱,则如果我们看到标记“71”,就是行标记为 7,列标记为 1 的单元格对应的数字 11,对应原始标记中第 11 个,即“很有钱”。那么标记“71 78 57”就表示原始标记的第 11、8、7 号,意思是“很有钱”、“没有防范”、“计划行动”。

table.JPG

本题就请你编写程序,自动破译小偷的新标记。

输入格式:

输入第一行给出 2 个正整数:N(≤100)为小偷的原始标记个数,M(≤10)为新标记对照矩阵的行数。

随后 N 行,第 i 行给出第 i 个标记的解释,由不超过 100 个英文字母和空格组成。

接下来一行给出 M 个数字,为 0 到 9 之间的数字,保证不重复,其中第 i 个数对应矩阵第 i 行。

接下来 M 行,每行给出 10 个数字,或者是 1 到 N 之间的一个编号,或者是 −1 表示没有对应的编号。

最后一行给出小偷留在墙上的数字标记,格式为:

k t[1] ... t[k]

其中 k 是数字个数(不超过 N),后面跟着 k 个数字。

输出格式:

对小偷留下的每个数字,在一行中输出其对应的意义,顺序与输入顺序相同。如果没有对应的意义,则在对应行中输出 ?

输入样例:

10 2
jia li you ren
kong fang zi
jia you e gou
dan shen
hen you qian
xiao xin lin ju
you bao jing qi
jin kuai dong shou
xia ci zai lai
bu bi jin ru
6 2
-1 6 5 1 -1 10 3 4 -1 9
2 4 7 -1 3 -1 5 -1 8 2
5 20 64 61 22 13

输出样例:

kong fang zi
?
xiao xin lin ju
you bao jing qi
?

AC 代码

#include <bits/stdc++.h>
using namespace std;
int r[11];
int nums[11][11];
int main()
{
    int n, m;
    int a;
    cin >> n >> m;
    vector<string> inform(n + 1);
    getchar();
    for (int i = 1; i <= n; i++)
    {
        getline(cin, inform[i]);
    }
    vector<int> hash(11);
    for (int i = 1; i <= m; i++)
    {
        cin >> hash[i];
    }
    for (int i = 1; i <= m; i++)
        for (int j = 0; j < 10; j++) 
		{
			cin >> nums[hash[i]][j];
		 
		} 
    // 开始询问
    int k = 0;
    cin >> k;
    while (k--)
    {
        int tmp = 0;
        cin >> tmp;
        int y = tmp % 10;
        int x = tmp / 10;
        if (nums[x][y] == -1 || nums[x][y] == 0) cout << "?" << endl;
        else cout << inform[nums[x][y]] << endl;
    }
    return 0;
}

L2 - 1 推宝塔

ta.jpg

堆宝塔游戏是让小朋友根据抓到的彩虹圈的直径大小,按照从大到小的顺序堆起宝塔。但彩虹圈不一定是按照直径的大小顺序抓到的。聪明宝宝采取的策略如下:

  • 首先准备两根柱子,一根 A 柱串宝塔,一根 B 柱用于临时叠放。
  • 把第 1 块彩虹圈作为第 1 座宝塔的基座,在 A 柱放好。
  • 将抓到的下一块彩虹圈 C 跟当前 A 柱宝塔最上面的彩虹圈比一下,如果比最上面的小,就直接放上去;否则把 C 跟 B 柱最上面的彩虹圈比一下:
    • 如果 B 柱是空的、或者 C 大,就在 B 柱上放好;
    • 否则把 A 柱上串好的宝塔取下来作为一件成品;然后把 B 柱上所有比 C 大的彩虹圈逐一取下放到 A 柱上,最后把 C 也放到 A 柱上。

重复此步骤,直到所有的彩虹圈都被抓完。最后 A 柱上剩下的宝塔作为一件成品,B 柱上剩下的彩虹圈被逐一取下,堆成另一座宝塔。问:宝宝一共堆出了几个宝塔?最高的宝塔有多少层?

输入格式:

输入第一行给出一个正整数 N(≤103),为彩虹圈的个数。第二行按照宝宝抓取的顺序给出 N 个不超过 100 的正整数,对应每个彩虹圈的直径。

输出格式:

在一行中输出宝宝堆出的宝塔个数,和最高的宝塔的层数。数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

11
10 8 9 5 12 11 4 3 1 9 15

输出样例:

4 5

 AC 代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 1010;
int nums[N];
int main()
{
    int n;
    cin >> n;
    vector<int> va;
    vector<int> vb;
    int cnt = 0;
    int res = 0;
    for(int i = 0; i < n; i++)
    {
        cin >> nums[i];
        if(va.size() == 0 || nums[i] < va.back()) 
            va.push_back(nums[i]);
        else if(vb.size() == 0 || nums[i] > vb.back())
            vb.push_back(nums[i]);
        else
        {
            res = max(res, (int)va.size());
            va.clear();
            cnt ++;
            while(vb.back() > nums[i])
            {
                int tm = vb.back();
                va.push_back(tm);
                vb.pop_back();
            }
            va.push_back(nums[i]);
        }
    }
    if(va.size() > 0) cnt ++;
    res = max(res, (int)va.size());
    cout << cnt  << " " << res << endl;
    return 0;
}

L2 - 2 含茶量

天梯赛模拟赛 L2 —— 含茶量

L2 - 3 到底爱不爱我

love.JPG

古代少女有了心上人时,会悄悄折一条树枝,揪那枝上的叶子,揪一片叶子念一句“爱我”,再揪一片念一句“不爱我”…… 这样揪落最后一片叶子的时候,看看是停在“爱”还是“不爱”。

但聪明的慧娘一眼洞穿,只要数一下叶子有多少片,根据这个数字的奇偶性判断是以“爱”开始还是以“不爱”开始,就总是可以最后落在“爱”上。这个游戏顿时就变得无趣了 —— 真的是文科生制造浪漫,理科生杀死浪漫。

于是有着工科生大脑的慧娘打算另外制作一个更有趣的浪漫游戏。她用不同植物的枝条做成了三种“情枝”:

  • “专情枝”:是一根有两个分岔的树枝,只有当两个分岔上连接的枝条传过来的情话都是“爱”的时候,这根枝条的根部才传出“爱”;否则树枝根部传出的是“不爱”。
  • “博爱枝”:也是一根有两个分岔的树枝,只有当两个分岔上连接的枝条传过来的情话都是“不爱”的时候,这根枝条的根部才传出“不爱”;否则树枝根部传出的都是“爱”。
  • “情变枝”:是没有分岔的一根直枝,如果一端接到“爱”,另一端必须传出“不爱”;反之如果一端接到“不爱”,另一端则会传出“爱”。

慧娘将这些树枝摆放在院子里,布了一个“情阵”,先选一根特殊的枝条作为初试一枝,从这枝条的根部开始,扩散开去,令它们根枝相连。然后她在末梢的枝杈旁随意写下“爱”或“不爱”。现在请你写个程序帮她算出来,在初始一枝的根部,她能得到“爱”还是“不爱”?

输入格式:

输入在第一行中给出正整数 N(≤30),是慧娘制作的情枝数量。这里假设她将所有的情枝从 1 到 N 做好了编号。随后 N 行,第 i 行给出第 i 枝的描述,格式为

类型 左分枝连接的编号 右分枝连接的编号

其中 类型 为 1 代表专情、2 代表博爱、3 代表情变。当然如果是情变枝,则后面跟的是其唯一末端连接的情枝编号,并没有两个分枝的信息。如果一个分枝是末梢,并没有连接其它枝条,则对应编号为 0。

接下来一行中给出正整数 K(≤30),是慧娘询问的次数。以下 K 行,每行给出一个由 0 和 1 组成的字符串,其中 0 表示“不爱”,1 表示“爱”—— 这是慧娘从左到右在每个枝杈末梢处写下的。(注意:“从左到右”的意思是,我们从初试一枝出发去遍历所有枝条的末梢时,总是遵循先遍历左边情阵、再遍历右边情阵的顺序)

输出格式:

对慧娘的每个询问,如果她在初始一枝的根部能得到“爱”,就输出 Ai;否则输出 BuAi

输入样例:

6
2 6 4
1 0 0
3 1
2 0 0
3 0
1 5 2
5
11111
00000
11100
10011
01100

输出样例:

BuAi
Ai
Ai
BuAi
BuAi

样例说明:

样例对应的情阵以及慧娘第 3 问的情势如图所示,其中完整的心对应 1,裂开的心对应 0

sample.jpg

AC 代码 

#include<bits/stdc++.h>
using namespace std;
const int N = 32;
int ty[31];
int con[31][3]; // 第 i 个分支左右连接的分支编号
int hapa[31]; // 记录 i 个分支是否有父节点 // 为了找父节点, 根节点没有父节点 
bool dfs(int x)
{
    if(x == 0) // 到了叶子节点,刚好输入数据! 
    {
        char ch;
        cin >> ch;
        return ch - '0';
    }
    if(ty[x] == 1)
        return dfs(con[x][0]) & dfs(con[x][1]);
    else if(ty[x] == 2)
        return dfs(con[x][0]) | dfs(con[x][1]);
    else return dfs(con[x][0]) ^ 1;
}
int main()
{
    int n = 0;
    cin >> n; // 情枝数量
    for(int i = 1; i <= n; i++)
    {
        cin >> ty[i];
        if(ty[i] == 1 || ty[i] == 2)
        {
            cin >> con[i][0];
            cin >> con[i][1];
            hapa[con[i][0]] ++; // 记录有父节点的情枝 
            hapa[con[i][1]] ++;
        }
        else 
        {
            cin >> con[i][0];
            hapa[con[i][0]] ++; // 记录有父节点的情枝 
        }
    }
    // 找到根节点
    int i = 0;
    for(i = 1; i <= n; i++)
    {
        if(hapa[i] == 0) break; 
    }
     // 根节点为 i 
    int k = 0; // 询问次数
    cin >> k;
    while(k--)
    {
        if(dfs(i)) cout << "Ai" << endl;
        else cout << "BuAi" << endl;
    }
    return 0;
}

L2 - 4 寻宝图

给定一幅地图,其中有水域,有陆地。被水域完全环绕的陆地是岛屿。有些岛屿上埋藏有宝藏,这些有宝藏的点也被标记出来了。本题就请你统计一下,给定的地图上一共有多少岛屿,其中有多少是有宝藏的岛屿。

输入格式:

输入第一行给出 2 个正整数 N 和 M(1<N×M≤105),是地图的尺寸,表示地图由 N 行 M 列格子构成。随后 N 行,每行给出 M 位个位数,其中 0 表示水域,1 表示陆地,2-9 表示宝藏。
注意:两个格子共享一条边时,才是“相邻”的。宝藏都埋在陆地上。默认地图外围全是水域。

输出格式:

在一行中输出 2 个整数,分别是岛屿的总数量和有宝藏的岛屿的数量。

输入样例:

10 11
01000000151
11000000111
00110000811
00110100010
00000000000
00000111000
00114111000
00110010000
00019000010
00120000001

输出样例:

7 2

过 96% 测试代码(24分)

#include <bits/stdc++.h>
using namespace std;
const int N = 10010;
int nums[N][N];
bool vis[N][N];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int m,n;
int cnt1, cnt2;
int flag;
void dfs(int i, int j)
{
	if(nums[i][j] > 1) flag = 1; // 防止进递归的第一个数就是大于 1 的数 
    for(int k = 0; k < 4; k++)
    {
        int x = i + dx[k];
        int y = j + dy[k];
        if(x >= 1 && x <= m && y >= 1 && y <= n && 
           !vis[x][y] && nums[x][y] > 0)
        {
            if(nums[x][y] > 1) flag = 1;
                vis[x][y] = true;
                dfs(x, y);
        }
    }
}
int main()
{
    cin >> m >> n;
    string s;
    for(int i = 1; i <= m; i++)
    {
        cin >> s;
        for(int j = 1; j <= n; j++)
        {
            nums[i][j] = s[j - 1] - '0';
        }
    }
    for(int i = 1; i <= m; i++)
        for(int j = 1; j <= n; j++)
            if(nums[i][j] > 0 && !vis[i][j])
            {
                cnt1++;
                vis[i][j] = true;
                dfs(i, j);
                if(flag == 1) cnt2 ++;
                flag = 0;
            }
    cout << cnt1 << " " << cnt2 << endl;
    return 0;
}

 

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值