首页 > 其他分享 >【洛谷 P8672】[蓝桥杯 2018 国 C] 交换次数 题解(字符串+映射+全排列)

【洛谷 P8672】[蓝桥杯 2018 国 C] 交换次数 题解(字符串+映射+全排列)

时间:2024-04-03 13:31:22浏览次数:20  
标签:P8672 字符 code 题解 ll 蓝桥 s20 s01 s02

[蓝桥杯 2018 国 C] 交换次数

题目描述

IT 产业人才需求节节攀升。业内巨头百度、阿里巴巴、腾讯(简称 BAT)在某海滩进行招聘活动。

招聘部门一字排开。由于是自由抢占席位,三大公司的席位随机交错在一起,形如:

ABABTATT,这使得应聘者十分别扭。

于是,管理部门要求招聘方进行必要的交换位置,使得每个集团的席位都挨在一起。即最后形如:

BBAAATTT 这样的形状,当然,也可能是:

AAABBTTT 等。

现在,假设每次只能交换 2 2 2 个席位,并且知道现在的席位分布,

你的任务是计算:要使每个集团的招聘席位都挨在一起需要至少进行多少次交换动作。

输入格式

输入是一行 n n n 个字符(只含有字母 BAT),表示现在的席位分布。

输出格式

输出是一个整数,表示至少交换次数。

样例 #1

样例输入 #1

TABTABBTTTT

样例输出 #1

3

样例 #2

样例输入 #2

TTAAABB

样例输出 #2

0

提示

输入字符串的长度 n n n 不大于 1 0 5 10^5 105。

时限 1 秒, 256M。蓝桥杯 2018 年第九届国赛


思路

从输入中读取席位分布,然后用一个 map 记录 ABT 的数量。定义了一个变量 ans,用来存储最小的交换次数,初始化为一个很大的数。然后定义了一个字符串 abt,是 ABT 的一个排列,然后使用 do while 循环,对 abt 进行全排列,调用 calc 函数计算需要交换的最小次数。

然后定义一个 calc 函数,该函数接受一个字符串,该字符串是 ABT 的一个排列,然后计算如果席位按照该排列进行排列,需要交换的最小次数。

calc 函数中,首先定义了两个变量 s01s02,这两个变量用来记录0区的字符需要移动到1区和2区的数量。然后遍历字符串的前 cnt[code[0]] 个字符,如果字符是 code[1],则 s01 加一,如果字符是 code[2],则 s02 加一。这个过程就是计算0区的字符需要移动的数量。

然后定义了两个变量 s20s21,这两个变量用来记录2区的字符需要移动到0区和1区的数量。然后遍历字符串的后 cnt[code[2]] 个字符,如果字符是 code[0],则 s20 加一,如果字符是 code[1],则 s21 加一。这个过程就是计算2区的字符需要移动的数量。

当0区和1区都完成排序后,2区自然也就排序完成了。不需要再检查2区。

s01s21 分别表示0区需要移到1区和2区需要移到1区的字符数量,这两部分的字符移动是必须的。至于 s02s20,表示0区需要移到2区和2区需要移到0区的字符数量,这两部分的字符移动存在冲突,即如果0区的字符移到2区,那么2区的字符就不能移到0区,反之亦然。因此,选择 s02s20 中的最大值,即选择需要移动的字符数量最多的区域进行移动。这样可以保证总的交换次数最少。

所以最少的交换次数等于0区需要移到1区的字符数量,加上2区需要移到1区的字符数量,再加上0区和2区中需要移动的字符数量最多的那个区域的字符数量。函数返回 sum = s01 + s21 + max(s02, s20);

对每一个排列,计算需要交换的最小次数,然后更新 ans。最后,输出 ans


AC代码

#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;

const int N = 1e6 + 7;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;

int n;
string s;
int len = s.length();
map<char, int> cnt;

/*
将字符串划分为0、1、2三个区域
每个区域排序后应该只有一种字符
*/
ll calc(string code) {
	ll sum = 0;

	ll s01 = 0;
	ll s02 = 0;
	// 检查0区
	for (int i = 0; i < cnt[code[0]]; i++) {
		// cout << s[i] << endl;
		if (s[i] == code[1]) {
			// 该字符属于1区,将其字符从0区移到1区
			s01++;
		} else if (s[i] == code[2]) {
			// 该字符属于2区,将其从0区移到2区
			s02++;
		}
	}

	ll s20 = 0;
	ll s21 = 0;
	// 检查2区
	for (int i = s.length() - 1; i >= s.length() - cnt[code[2]]; i--) {
		// cout << s[i] << endl;
		if (s[i] == code[1]) {
			// 该字符属于1区,将该字符从2区移到1区
			s21++;
		} else if (s[i] == code[0]) {
			// 该字符属于0区,将该字符从2区移到0区
			s20++;
		}
	}

	sum = s01 + s21 + max(s02, s20);
	// cout << sum << endl;
	return sum;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	cin >> s;
	for (const auto i : s) {
		cnt[i]++;
	}

	ll ans = INF;
	string abt = "ABT";
	do {
		ans = min(ans, calc(abt));
	} while (next_permutation(abt.begin(), abt.end()));
	cout << ans << "\n";
	return 0;
}

标签:P8672,字符,code,题解,ll,蓝桥,s20,s01,s02
From: https://blog.csdn.net/qq_34988204/article/details/137277018

相关文章

  • 【洛谷 P8700】[蓝桥杯 2019 国 B] 解谜游戏 题解(字符串+映射+周期性)
    [蓝桥杯2019国B]解谜游戏题目背景题目描述小明正在玩一款解谜游戏。谜题由242424根塑料棒组成,其中黄色塑料棒4......
  • 记录一次解决跨域问题解决过程。 strict-origin-when-cross-origin,net::ERR_FAILED, No
    事情是这样的,vue项目本地启动可以正常连接后端端口访问,部署到nginx上只有就无法访问,显示跨域问题  于是查看后端日志 啥都没有,觉得肯定是nginx的问题,怎么配置都没用, location/{ roothtml; indexindex.htmlindex.htm; add_header'Access-Control-Allow-O......
  • P3622 [APIO2007] 动物园 -题解
    好写爱写没事干所以有了这篇题解洛谷P3622[APIO2007]动物园题解$Link$hzoi题库洛谷题目说的挺繁琐,其实就传达了一个很简单的信息:\(n\)个动物,\(c\)个小孩,每个小孩能看到\(5\)个动物(所在的位置)\(E\)到\(E+4\),有\(F\)个害怕的动物,\(L\)个喜欢的动物。如果视野中有至......
  • 题解:P3903 导弹拦截III
    第一步:确定子任务因为当前拦截的导弹可能在奇数位上,也可能在偶数位上,所以以这两种状态为子任务。第二步:确定状态设$dp[i][0/1]$为作为第(偶数/奇数)个被拦截的导弹,最大可以拦截多少个导弹第三步:推出转移方程$dp[i][0]=max(dp[j][1])+1(1\lej<i且h[i]<h[j])$$dp[i][1]=max(......
  • P8776 [蓝桥杯 2022 省 A] 最长不下降子序列
    1.首先想到的做法设up_len[i]为以a[i]为结尾的最长不下降子序列的长度,down_len[i]表示以a[i]为开始的最长不下降子序列的长度。在求pre的过程中记录下额外信息:down_pre[i]表示在求down_len[i]的过程中,i是由哪个点转移过来的;得到dp的转移方程:if(down_pre[i])ans......
  • 题解:P2758 编辑距离
    第一步:确定子问题有4种操作(删除,添加,修改,不变)。所以4个子问题就是操作后的A变为B需要多少步。第二步:确定状态设$dp[i][j]$为将A的前i位变为B的前j位的最小代价。第三步:确定转移方程删除:$dp[i][j]=dp[i-1][j]+1$添加:$dp[i][j]=dp[i][j-1]+1$修改:$dp[i][j]=dp[i-1][j......
  • 蓝桥杯单片机组第十四届省赛
     1.题目 本次题目模块较多,难度较大  2.底层代码2.1三个常用模块2.1.1按键本次省赛采用了NE555模块,要用P34引脚,在按键底层中,要把P34相关的代码注释掉,并且要将P34引脚用跳线帽(可以用超声波模块的跳线帽)与SIGNAL相连Key.c#include<Key.h>unsignedchar......
  • 蓝桥杯单片机第十三届省赛
    一、题目这次的省赛我感觉还是比较基础的,掌握几个模块就可以完全写出题目是在在网上找的二、代码 main.c#include<STC15F2K60S2.H>#include<ds1302.h>#include<onewire.h>#include<intrins.h>#include<Init.h>#include<Key.h>#include<Seg.h>#include......
  • 蓝桥杯算法集训 - Week 5:树状数组、各类DP算法
    蓝桥杯算法集训-Week5本系列随笔用于整理AcWing题单——《蓝桥杯集训·每日一题2024》的系列题型及其对应的算法模板。一、树状数组树状数组是一种数据结构,可以快速地完成以下两个操作:将第i个数加上c快速求前缀和,即任意区间[i,j]的和Ⅰ、代码模板//树状数组长度......
  • AGC066 题解
    题解:AT_agc066_a[AGC066A]AdjacentDifference笑点解析:没有必要将总成本最小化。我们将格子间隔的黑白染色(显然有两种染色方法),对于黑点我们要求它是奇数倍\(d\),对于白点我们要求它是偶数倍\(d\),这样一定满足相邻格子相差至少\(d\)。因为两种染色方法的代价和为\(dN^2\),......