本人能力有限,只做出前三题。有时间会看一下后面三题。
前两题很简单,直接上代码,第三题用到了二分法(有详解)。
1. 三带一【算法赛】
问题描述
小蓝和小桥玩斗地主,小蓝只剩四张牌了,他想知道是否是“三带一”牌型。所谓“三带一”牌型,即四张手牌中,有三张牌一样,另外一张不与其他牌相同,换种说法,四张手牌经过重新排列后,可以组成 型。
输入格式
第一行输入一个整数 ,代表斗地主的轮数。接下来 行,每行输入一个长度为 的字符串,代表小蓝的手牌。字符 { 'A','2','3','4','5','6','7','8','9','X','J','Q','K' } 对应代表牌面 { } 。牌面中不包含大小王。
输出格式
输出 行,每行一个字符串,如果当前牌是“三带一”牌型,输出 Yes ,否则输出 No 。
样例输入
5
AAAA
33X3
JQKX
6566
KKKQ
样例输出
No
Yes
No
Yes
Yes
说明“四炸”牌型不属于“三带一”牌型。
评测数据范围
数据范围: 。字符中只包含:{ } 。
AC代码
只需要判断是否存在三个相同字符即可。
signed main()
{
int t;
cin >> t;
while (t--)
{
map<char, int> m;
string s;
cin >> s;
for (int i = 0; i < s.size(); i++)
{
m[s[i]]++;
}
bool f = false;
for (auto i : m)
{
if (i.second == 3)
{
cout << "Yes" << endl;
f = true;
break;
}
}
if (!f) cout << "No" << endl;
}
return 0;
}
2. 数树数【算法赛】
问题描述
小蓝最近学了二叉树,他想到了一个问题。 给定一个层数为 的满二叉树,每个点编号规则如下:具体来说,二叉树从上向下数第 层,从左往右编号分别为: 。\n\n小蓝给你一条从根节点开始的路径,他想知道到达的节点编号是多少。例如:路径是 ,那么到达的节点是 ,最后到了三号点。
输入格式
第一行输入两个整数 , 表示完全二叉树的层数, 代表询问的路径数量。接下来 行,每行一个字符串 , 只包含字符 { 'L','R' },'L' 代表向左,R 代表向右。
输出格式
输出 行,每行输出一个整数,代表最后到达的节点编号。
样例输入
3 6 R L LL LR RL RR
样例输出
2 1 1 2 3 4
说明
。 完全二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为 ,且节点总数是 ,则它就是满二叉树。
思路
简单提示一下,多花几层二叉树,观察一下就可以发现,走R的话是当前结点编号* 2,走L的话,是2* 当前结点编号-1。
AC代码
signed main()
{
int n, t;
cin >> n >> t;
while (t--)
{
int k = 1;
string s;
cin >> s;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == 'R') k *= 2;
else k = 2*k - 1;
}
cout << k << endl;
}
return 0;
}
3. 分组【算法赛】
问题描述
蓝桥小学要进行弹弹球游戏,二年级一班总共有 个同学,要求分成 个队伍,由于弹弹球游戏要求队员的身高差不能太大,小蓝是班长,他对这个事情正在发愁,他想问你,如何最小化每个组之间的身高极差。具体的,假设分成了 个组,第 组最高的人身高是 ,最矮的是 ,你被要求最小化表达式: 。直白来说,你需要将 个元素分出 组,使得最大的极差尽可能小。你需要输出这个最小化后的值。
输入格式
第一行输入两个整数 。 第二行输入 个整数: ,分别代表 个人的身高。
输出格式
输出一个整数,代表最小值。
样例输入
5 3
8 4 3 6 9
样例输出
1
说明
样例分组情况:{ } ,{ } ,{ } 。
评测数据规模
数据范围: 。
解题思路
读了一遍题,没什么思路,再读一遍,观察数据,可以发现最小的极差和最大的极差都是可以确定的,最小的就是0,很好理解,最大的就是h[n-1] - h[0](或者无脑一些直接1e9)。这样大的数据范围,立马就想到用二分来做。这里,我们二分的是可能的最小化极差。然后就该构造二分答案的check()函数了,在二分的过程中,我们必须保证分成的组数为k,那如何实现呢?
只需将排序后的数组进行遍历,记录当前组的最矮身高,如果当前成员身高在该组中与最矮成员身高差大于mid,则将其重新分一组。最后看组数是否小于等于k
为什么要小于等于k呢?而不是大于等于?
极差相同的情况下,分的组越少,说明情况越乐观,如过满足cnt<=k,说明mid符合条件,我们还能进一步缩小右侧范围,看看比mid小的部分能否满足条件(我们的目标就是要找到max极差的最小化的值),反之,缩小左侧范围即可。
AC代码
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
#define endl '\n'
typedef long long ll;
const int N = 100010;
int h[N];
int n, k;
bool check(int m)
{
int cnt = 1;//组数
int minh = h[0];//当前组最小的身高
for (int i = 1; i < n; i++)
{
if (h[i]-minh > m)//当前成员身高在该组中与最矮成员身高差过大,将其新分一组
{
cnt++;
minh = h[i];
}
}
if (cnt <= k) return true; //组数越少,极差越小
else return false;
//return cnt<= k;
}
signed main()
{
cin >> n >> k;
for (int i = 0; i < n; i++)
{
cin >> h[i];
}
sort(h, h + n);
int l = 0, r = 1e9;
while (l < r)
{
int mid = (l + r) / 2;
if (check(mid))
{
r = mid;
}
else
{
l = mid + 1;
}
}
cout << l;
return 0;
}